
- •Предисловие
- •Структура книги
- •Глава 1. Начинаем
- •1.1. Решение задачи
- •1.2. Программа на языке C++
- •1.2.1. Порядок выполнения инструкций
- •1.3. Директивы препроцессора
- •1.4. Немного о комментариях
- •1.5. Первый взгляд на ввод/вывод
- •1.5.1. Файловый ввод/вывод
- •Глава 2. Краткий обзор С++
- •2.1. Встроенный тип данных “массив”
- •2.2. Динамическое выделение памяти и указатели
- •2.3. Объектный подход
- •2.4. Объектно-ориентированный подход
- •2.5. Использование шаблонов
- •2.6. Использование исключений
- •2.7. Использование пространства имен
- •2.8. Стандартный массив – это вектор
- •Глава 3. Типы данных С++
- •3.1. Литералы
- •3.2. Переменные
- •3.2.1. Что такое переменная
- •3.2.2. Имя переменной
- •3.2.3. Определение объекта
- •3.3. Указатели
- •3.4. Строковые типы
- •3.4.1. Встроенный строковый тип
- •3.4.2. Класс string
- •3.5. Спецификатор const
- •3.6. Ссылочный тип
- •3.7. Тип bool
- •3.8. Перечисления
- •3.9. Тип “массив”
- •3.9.1. Многомерные массивы
- •3.9.2. Взаимосвязь массивов и указателей
- •3.10. Класс vector
- •3.13. Спецификатор volatile
- •3.14. Класс pair
- •3.15. Типы классов
- •Глава 4. Выражения
- •4.1. Что такое выражение?
- •4.3. Операции сравнения и логические операции
- •4.4. Операции присваивания
- •4.5. Операции инкремента и декремента
- •4.6. Операции с комплексными числами
- •4.7. Условное выражение
- •4.8. Оператор sizeof
- •4.9. Операторы new и delete
- •4.10. Оператор “запятая”
- •4.11. Побитовые операторы
- •4.12. Класс bitset
- •4.13. Приоритеты
- •4.14. Преобразования типов
- •4.14.1. Неявное преобразование типов
- •4.14.2. Арифметические преобразования типов
- •4.14.3. Явное преобразование типов
- •4.14.4. Устаревшая форма явного преобразования
- •4.15. Пример: реализация класса Stack
- •Глава 5. Инструкции
- •5.1. Простые и составные инструкции
- •5.2. Инструкции объявления
- •5.3. Инструкция if
- •5.4. Инструкция switch
- •5.5. Инструкция цикла for
- •5.6. Инструкция while
- •5.8. Инструкция do while
- •5.8. Инструкция break
- •5.9. Инструкция continue
- •5.10. Инструкция goto
- •5.11. Пример связанного списка
- •5.11.1. Обобщенный список
- •Глава 6. Абстрактные контейнерные типы
- •6.1. Система текстового поиска
- •6.2. Вектор или список?
- •6.3. Как растет вектор?
- •6.4. Как определить последовательный контейнер?
- •6.5. Итераторы
- •6.6. Операции с последовательными контейнерами
- •6.6.1. Удаление
- •6.6.2. Присваивание и обмен
- •6.6.3. Обобщенные алгоритмы
- •6.7. Читаем текстовый файл
- •6.8. Выделяем слова в строке
- •6.9. Обрабатываем знаки препинания
- •6.10. Приводим слова к стандартной форме
- •6.11. Дополнительные операции со строками
- •6.12. Строим отображение позиций слов
- •6.12.2. Поиск и извлечение элемента отображения
- •6.12.3. Навигация по элементам отображения
- •6.12.4. Словарь
- •6.12.5. Удаление элементов map
- •6.13. Построение набора стоп-слов
- •6.13.2. Поиск элемента
- •6.13.3. Навигация по множеству
- •6.14. Окончательная программа
- •6.15. Контейнеры multimap и multiset
- •6.16. Стек
- •6.17. Очередь и очередь с приоритетами
- •6.18. Вернемся в классу iStack
- •Глава 7. Функции
- •7.1. Введение
- •7.2. Прототип функции
- •7.2.1. Тип возвращаемого функцией значения
- •7.2.2. Список параметров функции
- •7.2.3. Проверка типов формальных параметров
- •7.3. Передача аргументов
- •7.3.1. Параметры-ссылки
- •7.3.2. Параметры-ссылки и параметры-указатели
- •7.3.3. Параметры-массивы
- •7.3.5. Значения параметров по умолчанию
- •7.3.6. Многоточие
- •7.4. Возврат значения
- •7.5. Рекурсия
- •7.6. Встроенные функции
- •7.8.1. Класс для обработки параметров командной строки
- •7.9. Указатели на функции
- •7.9.1. Тип указателя на функцию
- •7.9.2. Инициализация и присваивание
- •7.9.3. Вызов
- •7.9.4. Массивы указателей на функции
- •7.9.5. Параметры и тип возврата
- •Глава 8. Область видимости и время жизни
- •8.1. Область видимости
- •8.1.1. Локальная область видимости
- •8.2. Глобальные объекты и функции
- •8.2.1. Объявления и определения
- •8.2.2. Сопоставление объявлений в разных файлах
- •8.2.3. Несколько слов о заголовочных файлах
- •8.3.1. Автоматические объекты
- •8.3.2. Регистровые автоматические объекты
- •8.3.3. Статические локальные объекты
- •8.4. Динамически размещаемые объекты
- •8.4.3. Динамическое создание и уничтожение массивов
- •8.5.1. Определения пространства имен
- •8.5.2. Оператор разрешения области видимости
- •8.5.3. Вложенные пространства имен
- •8.5.4. Определение члена пространства имен
- •8.5.6. Безымянные пространства имен
- •8.6.1. Псевдонимы пространства имен
- •8.6.2. Using-объявления
- •8.6.3. Using-директивы
- •8.6.4. Стандартное пространство имен std
- •Глава 9. Перегруженные функции
- •9.1. Объявления перегруженных функций
- •9.1.1. Зачем нужно перегружать имя функции
- •9.1.2. Как перегрузить имя функции
- •9.1.3. Когда не надо перегружать имя функции
- •9.2. Три шага разрешения перегрузки
- •9.3.1. Подробнее о точном соответствии
- •9.3.2. Подробнее о расширении типов
- •9.3.3. Подробнее о стандартном преобразовании
- •9.3.4. Ссылки
- •9.4. Детали разрешения перегрузки функций
- •9.4.1. Функции-кандидаты
- •9.4.2. Устоявшие функции
- •9.4.3. Наилучшая из устоявших функция
- •9.4.4. Аргументы со значениями по умолчанию
- •Глава 10. Шаблоны функций
- •10.1. Определение шаблона функции
- •10.2. Конкретизация шаблона функции
- •10.5.1. Модель компиляции с включением
- •10.5.2. Модель компиляции с разделением
- •10.5.3. Явные объявления конкретизации
- •10.11. Пример шаблона функции
- •Глава 11. Обработка исключений
- •11.1. Возбуждение исключения
- •11.2. try-блок
- •11.3. Перехват исключений
- •11.3.1. Объекты-исключения
- •11.3.2. Раскрутка стека
- •11.3.3. Повторное возбуждение исключения
- •11.3.4. Перехват всех исключений
- •11.4. Спецификации исключений
- •11.4.1. Спецификации исключений и указатели на функции
- •11.5. Исключения и вопросы проектирования
- •Глава 12. Обобщенные алгоритмы
- •12.1. Краткий обзор
- •12.2. Использование обобщенных алгоритмов
- •12.3. Объекты-функции
- •12.3.1. Предопределенные объекты-функции
- •12.3.3. Сравнительные объекты-функции
- •12.3.4. Логические объекты-функции
- •12.3.5. Адаптеры функций для объектов-функций
- •12.3.6. Реализация объекта-функции
- •12.4. Еще раз об итераторах
- •12.4.1. Итераторы вставки
- •12.4.2. Обратные итераторы
- •12.4.3. Потоковые итераторы
- •12.4.4. Итератор istream_iterator
- •12.4.5. Итератор ostream_iterator
- •12.4.6. Пять категорий итераторов
- •12.5.1. Алгоритмы поиска
- •12.5.2. Алгоритмы сортировки и упорядочения
- •12.5.3. Алгоритмы удаления и подстановки
- •12.5.4. Алгоритмы перестановки
- •12.5.5. Численные алгоритмы
- •12.5.6. Алгоритмы генерирования и модификации
- •12.5.8. Алгоритмы работы с множествами
- •12.5.9. Алгоритмы работы с хипом
- •12.6.1. Операция list_merge()
- •12.6.2. Операция list::remove()
- •12.6.3. Операция list::remove_if()
- •12.6.5. Операция list::sort()
- •12.6.6. Операция list::splice()
- •12.6.7. Операция list::unique()
- •Глава 13. Классы
- •13.1. Определение класса
- •13.1.1. Данные-члены
- •13.1.2. Функции-члены
- •13.1.3. Доступ к членам
- •13.1.4. Друзья
- •13.1.5. Объявление и определение класса
- •13.3. Функции-члены класса
- •13.3.1. Когда использовать встроенные функции-члены
- •13.3.2. Доступ к членам класса
- •13.3.3. Закрытые и открытые функции-члены
- •13.3.4. Специальные функции-члены
- •13.3.5. Функции-члены со спецификаторами const и volatile
- •13.3.6. Объявление mutable
- •13.4. Неявный указатель this
- •13.4.1. Когда использовать указатель this
- •13.5. Статические члены класса
- •13.5.1. Статические функции-члены
- •13.6. Указатель на член класса
- •13.6.1. Тип члена класса
- •13.6.2. Работа с указателями на члены класса
- •13.6.3. Указатели на статические члены класса
- •13.7. Объединение – класс, экономящий память
- •13.8. Битовое поле – член, экономящий память
- •13.9.1. Разрешение имен в области видимости класса
- •Глава 14. Инициализация, присваивание и уничтожение класса
- •14.1. Инициализация класса
- •14.2. Конструктор класса
- •14.2.1. Конструктор по умолчанию
- •14.2.2. Ограничение прав на создание объекта
- •14.2.3. Копирующий конструктор
- •14.3. Деструктор класса
- •14.3.1. Явный вызов деструктора
- •14.3.2. Опасность увеличения размера программы
- •14.4. Массивы и векторы объектов
- •14.4.2. Вектор объектов
- •14.5. Список инициализации членов
- •14.6.1. Инициализация члена, являющегося объектом класса
- •Глава 15. Перегруженные операторы и определенные пользователем преобразования
- •15.1. Перегрузка операторов
- •15.1.1. Члены и не члены класса
- •15.1.2. Имена перегруженных операторов
- •15.1.3. Разработка перегруженных операторов
- •15.2. Друзья
- •15.3. Оператор =
- •15.4. Оператор взятия индекса
- •15.5. Оператор вызова функции
- •15.6. Оператор “стрелка”
- •15.7. Операторы инкремента и декремента
- •15.8. Операторы new и delete
- •15.8.1. Операторы new[ ] и delete [ ]
- •15.8.2. Оператор размещения new() и оператор delete()
- •15.9. Определенные пользователем преобразования
- •15.9.1. Конвертеры
- •15.9.2. Конструктор как конвертер
- •15.10.1. Еще раз о разрешении перегрузки функций
- •15.10.2. Функции-кандидаты
- •15.11.1. Объявления перегруженных функций-членов
- •15.11.2. Функции-кандидаты
- •15.11.3. Устоявшие функции
- •15.12.1. Операторные функции-кандидаты
- •15.12.2. Устоявшие функции
- •15.12.3. Неоднозначность
- •Глава 16. Шаблоны классов
- •16.1. Определение шаблона класса
- •16.1.1. Определения шаблонов классов Queue и QueueItem
- •16.2. Конкретизация шаблона класса
- •16.2.1. Аргументы шаблона для параметров-констант
- •16.3. Функции-члены шаблонов классов
- •16.3.1. Функции-члены шаблонов Queue и QueueItem
- •16.4. Объявления друзей в шаблонах классов
- •16.4.1. Объявления друзей в шаблонах Queue и QueueItem
- •16.5. Статические члены шаблонов класса
- •16.6. Вложенные типы шаблонов классов
- •16.7. Шаблоны-члены
- •16.8.2. Модель компиляции с разделением
- •16.8.3. Явные объявления конкретизации
- •16.12. Пространства имен и шаблоны классов
- •16.13. Шаблон класса Array
- •Глава 17. Наследование и подтипизация классов
- •17.1. Определение иерархии классов
- •17.1.1. Объектно-ориентированное проектирование
- •17.2. Идентификация членов иерархии
- •17.2.1. Определение базового класса
- •17.2.3. Резюме
- •17.3. Доступ к членам базового класса
- •17.4. Конструирование базового и производного классов
- •17.4.1. Конструктор базового класса
- •17.4.2. Конструктор производного класса
- •17.4.3. Альтернативная иерархия классов
- •17.4.4. Отложенное обнаружение ошибок
- •17.4.5. Деструкторы
- •17.5.1. Виртуальный ввод/вывод
- •17.5.2. Чисто виртуальные функции
- •17.5.3. Статический вызов виртуальной функции
- •17.5.4. Виртуальные функции и аргументы по умолчанию
- •17.5.5. Виртуальные деструкторы
- •17.5.6. Виртуальная функция eval()
- •17.5.7. Почти виртуальный оператор new
- •17.5.8. Виртуальные функции, конструкторы и деструкторы
- •17.7. Управляющий класс UserQuery
- •17.7.1. Определение класса UserQuery
- •17.8. Соберем все вместе
- •Глава 18. Множественное и виртуальное наследование
- •18.1. Готовим сцену
- •18.2. Множественное наследование
- •18.3. Открытое, закрытое и защищенное наследование
- •18.3.1. Наследование и композиция
- •18.3.2. Открытие отдельных членов
- •18.3.3. Защищенное наследование
- •18.3.4. Композиция объектов
- •18.4. Область видимости класса и наследование
- •18.5.1. Объявление виртуального базового класса
- •18.5.2. Специальная семантика инициализации
- •18.5.3. Порядок вызова конструкторов и деструкторов
- •18.5.4. Видимость членов виртуального базового класса
- •18.6.2. Порождение класса отсортированного массива
- •18.6.3. Класс массива с множественным наследованием
- •19.1. Идентификация типов во время выполнения
- •19.1.1. Оператор dynamic_cast
- •19.1.2. Оператор typeid
- •19.1.3. Класс type_info
- •19.2. Исключения и наследование
- •19.2.1. Исключения, определенные как иерархии классов
- •19.2.2. Возбуждение исключения типа класса
- •19.2.4. Объекты-исключения и виртуальные функции
- •19.2.5. Раскрутка стека и вызов деструкторов
- •19.2.6. Спецификации исключений
- •19.2.7. Конструкторы и функциональные try-блоки
- •19.3.1. Функции-кандидаты
- •19.3.3. Наилучшая из устоявших функций
- •Глава 20. Библиотека IOSTREAM
- •20.1. Оператор вывода <<
- •20.2. Ввод
- •20.2.1. Строковый ввод
- •20.3. Дополнительные операторы ввода/вывода
- •20.4. Перегрузка оператора вывода
- •20.5. Перегрузка оператора ввода
- •20.6. Файловый ввод/вывод
- •20.7. Состояния потока
- •20.8. Строковые потоки
- •20.9. Состояние формата
- •20.10. Сильно типизированная библиотека
- •Приложение
- •Глава 21. Обобщенные алгоритмы в алфавитном порядке
- •accumulate()
- •adjacent_difference()
- •adjacent_find()
- •binary_search()
- •copy()
- •copy_backward()
- •count_if()
- •equal()
- •equal_range()
- •fill()
- •find()
- •find_if()
- •find_end()
- •find_first_of()
- •generate()
- •generate_n()
- •includes()
- •inplace_merge()
- •iter_swap()
- •lexicographical_compare()
- •max_element()
- •merge()
- •mismatch()
- •next_permutation()
- •nth_element()
- •partial_sort()
- •partial_sort_copy()
- •partial_sum()
- •partition()
- •prev_permutation()
- •random_shuffle()
- •remove()
- •remove_copy()
- •remove_if()
- •remove_copy_if()
- •replace()
- •replace_copy()
- •replace_if()
- •replace_copy_if()
- •reverse_copy()
- •rotate()
- •search_n()
- •set_intersection()
- •set_union()
- •sort()
- •stable_partition()
- •swap()
- •swap_ranges()
- •transform()
- •unique_copy()
- •upper_bound()
- •Алгоритмы для работы с хипом
- •make_heap()
- •pop_heap()
- •push_heap()
- •sort_heap()

С++ для начинающих |
602 |
class Screen { public:
int height() { return _height; } int width() { return _width; }
//...
private:
short _heigh, _width;
//...
};
Применение оператора доступа к указателю на объект класса эквивалентно последовательному выполнению двух операций: применению оператора разыменования (*) к указателю, чтобы получить адресуемый объект, и последующему применению оператора “точка” для доступа к нужному члену класса. Например, выражение
s2->height()
можно переписать так:
(*s2).height()
Результат будет одним и тем же.
13.3. Функции-члены класса
Функции-члены реализуют набор операций, применимых к объектам класса. Например,
class Screen { public:
void home() { _cursor = 0; }
char get() { return _screen[_cursor]; } char get( int, int );
void move( int, int );
bool checkRange( int, int ); int height() { return _height; } int width() { return _width; } // ...
для Screen такой набор состоит из следующих объявленных в нем функций-членов:
};
Хотя у любого объекта класса есть собственная копия всех данных-членов, каждая
Screen myScreen, groupScreen; myScreen.home();
функция-член существует в единственном экземпляре:
groupScreen.home();
При вызове функции home() для объекта myScreen происходит обращение к его члену _cursor. Когда же эта функция вызывается для объекта groupScreen, то она обращается

С++ для начинающих |
603 |
к члену _cursor именно этого объекта, причем сама функция home() одна и та же. Как же может одна функция-член обращаться к данным-членам разных объектов? Для этого применяется указатель this, рассматриваемый в следующем разделе.
13.3.1. Когда использовать встроенные функции-члены
Обратите внимание, что определения функций home(), get(), height() и width() приведены прямо в теле класса. Такие функции называются встроенными. (Мы говорили об этом в разделе 7.6.)
Функции-члены можно объявить в теле класса встроенными и явно, поместив перед
class Screen { public:
//использование ключевого слова inline
//для объявления встроенных функций-членов
inline void home() { _cursor = 0; }
inline char get() { return _screen[_cursor]; } // ...
типом возвращаемого значения ключевое слово inline:
};
Определения home() и get() в приведенных примерах эквивалентны. Поскольку ключевое слово inline избыточно, мы в этой книге не пишем его явно для функцийчленов, определенных в теле класса.
Функции-члены, состоящие из двух или более строк, лучше определять вне тела. Для идентификации функции как члена некоторого класса требуется специальный синтаксис объявления: имя функции должно быть квалифицировано именем ее класса. Вот как
#include <iostream> #include "screen.h"
// имя функции-члена квалифицировано именем Screen::
bool Screen::checkRange( int row, int col ) { // проверить корректность координат
if ( row < 1 || row > _height || col < 1 || col > _width ) {
cerr << "Screen coordinates ( "
<<row << ", " << col
<<" ) out of bounds.\n"; return false;
}
return true;
выглядит определение функции checkRange(), квалифицированное именем Screen:
}
Прежде чем определять функцию-член вне тела класса, необходимо объявить ее внутри тела, обеспечив ее видимость. Например, если бы перед определением функции checkRange() не был включен заголовочный файл Screen.h, то компилятор выдал бы сообщение об ошибке. Тело класса определяет полный список его членов. Этот список не может быть расширен после закрытия тела.

С++ для начинающих |
604 |
Обычно функции-члены, определенные вне тела класса, не делают встроенными. Но объявить такую функцию встроенной можно, если явно добавить слово inline в объявление функции внутри тела класса или в ее определение вне тела, либо сделав то и другое одновременно. В следующем примере move() определена как встроенная функция-
inline void Screen::move( int r, int c )
{ // переместить курсор в абсолютную позицию
if ( checkRange( r, c ) ) // позиция на экране задана корректно?
{
int row = (r-1) * _width; // смещение начала строки _cursor = row + c - 1;
}
член класса Screen:
}
class Screen { public:
inline char get( int, int );
// объявления других функций-членов не изменяются
Функция get(int, int) объявляется встроенной с помощью слова inline:
};
Определение функции следует после объявления класса. При этом слово inline можно
char Screen::get( int r, int c )
{ |
// устанавливаем _cursor |
move( r, c ); |
|
return get(); |
// вызываем другую функцию-член get() |
опустить:
}
Так как встроенные функции-члены должны быть определены в каждом исходном файле, где они вызываются, то встроенную функцию, не определенную в теле класса, следует поместить в тот же заголовочный файл, в котором определен ее класс. Например, представленные ранее определения move() и get() должны находиться в заголовочном файле Screen.h после определения класса Screen.
13.3.2. Доступ к членам класса
Говорят, что определение функции-члена принадлежит области видимости класса независимо от того, находится ли оно вне или внутри его тела. Отсюда следуют два вывода:
•в определении функции-члена могут быть обращения к любым членам класса, открытым или закрытым, и это не нарушает ограничений доступа;
•когда функция-член обращается к членам класса, операторы доступа “точка” и “стрелка” не необходимы.

С++ для начинающих |
605 |
#include <string>
void Screen::copy( const Screen &sobj )
{
//если этот объект и объект sobj - одно и то же,
//копирование излишне
//мы анализируем указатель this (см. раздел 13.4)
if ( this != &sobj )
{
_height = sobj._height; _width = sobj._width; _cursor = 0;
//создаем новую строку;
//ее содержимое такое же, как sobj._screen
_screen = sobj._screen;
}
Например:
}
Хотя _screen, _height, _width и _cursor являются закрытыми членами класса Screen, функция-член copy() работает с ними напрямую. Если при обращении к члену отсутствует оператор доступа, то считается, что речь идет о члене того класса, для
#include "Screen.h"
int main()
{
Screen s1;
// Установить s1
Screen s2; s2.copy(s1);
// ...
которого функция-член вызвана. Если вызвать copy() следующим образом:
}
то параметр sobj внутри определения copy() соотносится с объектом s1 из функции main(). Функция-член copy() вызвана для объекта s2, стоящего перед оператором “точка”. Для такого вызова члены _screen, _height, _width и _cursor, при обращении к которым внутри определения этой функции нет оператора доступа, – это члены объекта s2. В следующем разделе мы рассмотрим доступ к членам класса внутри определения функции-члена более подробно и, в частности, покажем, как для поддержки такого доступа применяется указатель this.
13.3.3. Закрытые и открытые функции-члены
Функцию-член можно объявить в любой из секций public, private или protected тела класса. Где именно это следует делать? Открытая функция-член задает операцию, которая может понадобиться пользователю. Множество открытых функций-членов

С++ для начинающих |
606 |
составляет интерфейс класса. Например, функции-члены home(), move() и get() класса Screen определяют операции, с помощью которых программа манипулирует объектами этого типа.
Поскольку мы прячем от пользователей внутреннее представление класса, объявляя его члены закрытыми, то для манипуляции объектами типа Screen необходимо предоставить открытые функции-члены. Такой прием – сокрытие информации – защищает написанный пользователем код от изменений во внутреннем представлении.
Внутреннее состояние объекта класса также защищено от случайных изменений. Все модификации объекта производятся с помощью небольшого набора функций, что существенно облегчает сопровождение и доказательство правильности программы.
До сих пор мы встречались лишь с функциями, поддерживающими доступ к закрытым членам только для чтения. Ниже приведены две функции set(), позволяющие
class Screen { public:
void set( const string &s );
void set( char ch );
// объявления других функций-членов не изменяются
пользователю модифицировать объект Screen. Добавим их объявления в тело класса:
};
void Screen::set( const string &s )
{ // писать в строку, начиная с текущей позиции курсора
int space = remainingSpace(); int len = s.size();
if ( space < len ) {
cerr << "Screen: warning: truncation: "
<<"space: " << space
<<"string length: " << len << endl; len = space;
}
_screen.replace( _cursor, len, s ); _cursor += len - 1;
}
void Screen::set( char ch )
{
if ( ch == '\0' )
cerr << "Screen: warning: "
<< "null character (ignored).\n"; else _screen[_cursor] = ch;
Далее следуют определения функций:
}
В реализации класса Screen мы предполагаем, что объект Screen не содержит двоичных нулей. По этой причине set() не позволяет записать на экран нуль.
Представленные до сих пор функции-члены были открытыми, их можно вызывать из любого места программы, а закрытые вызываются только из других функций-членов (или

С++ для начинающих |
607 |
друзей) класса, но не из программы, обеспечивая поддержку другим операциям в реализации абстракции класса. Примером может служить функция-член remainingSpace
class Screen {
public:
// объявления других функций-членов не изменяются private:
inline int remainingSpace();
класса Screen(), использованная в set(const string&).
};
inline int Screen::remainingSpace()
{
int sz = _width * _height; return ( sz - _cursor );
remainingSpace() сообщает, сколько места осталось на экране:
}
(Детально защищенные функции-члены будут рассмотрены в главе 17.)
Следующая программа предназначена для тестирования описанных к настоящему
#include "Screen.h" #include <iostream>
int main() {
Screen sobj(3,3); // конструктор определен в разделе 13.3.4 string init("abcdefghi");
cout << "Screen Object ( "
<<sobj.height() << ", "
<<sobj.width() << " )\n\n";
//Задать содержимое экрана string::size_type initpos = 0;
for ( int ix = 1; ix <= sobj.width(); ++ix ) for ( int iy = 1; iy <= sobj.height(); ++iy )
{
sobj.move( ix, iy ); sobj.set( init[ initpos++ ] );
}
//Напечатать содержимое экрана
for ( int ix = 1; ix <= sobj.width(); ++ix )
{
for ( int iy = 1; iy <= sobj.height(); ++iy ) cout << sobj.get( ix, iy );
cout << "\n";
}
return 0;
моменту функций-членов:
}