
- •1.2 Философские замечания
- •1.3 Процедурное программирование
- •1.4 Модульное программирование
- •1.5 Абстракция данных
- •1.6 Пределы абстракции данных
- •1.7 Объектно-ориентированное программирование
- •1.8 Концепции объектно-ориентированного программирования
- •1.8.1 Инкапсуляция
- •1.8.2 Полиморфизм
- •1.8.3 Наследование
- •1.10 Несколько полезных советов
- •2.2 Перегрузка функций
- •2.3 Перегрузка операторов
- •2.4 Наследование
- •2.5 Конструкторы и деструкторы
- •2.7 Два новых типа данных
- •Глава 3. Классы и объекты
- •3.1 Параметризованные конструкторы
- •3.2 Дружественные функции
- •3.3 Значения аргументов функции по умолчанию
- •3.3.1 Корректное использование аргументов по умолчанию
- •3.4 Взаимосвязь классов и структур
- •3.5 Связь объединений и классов
- •3.6 Анонимные объединения
- •3.7 Inline-функции
- •3.7.1 Создание inline-функций внутри класса
- •3.8 Передача объектов в функции
- •3.9 Возвращение объектов функциями
- •3.10 Присваивание объектов
- •3.11 Конструктор копирования
- •3.12 Массивы объектов
- •3.12.1 Инициализация массивов объектов
- •3.12.2 Создание инициализированных и неинициализированных массивов
- •3.13 Указатели на объекты
- •3.14 Статические члены класса
- •Глава 4. Перегрузка функций и операторов
- •4.1 Перегрузка конструкторов
- •4.2 Локализация переменных
- •4.3 Локализация создания объектов
- •4.4 Перегрузка функций и неопределенность
- •4.5 Определение адреса перегруженной функции
- •4.6 Указатель this
- •4.7 Перегрузка операторов
- •4.8 Дружественная функция-оператор
- •4.9 Ссылки
- •4.9.1 Параметры-ссылки
- •4.9.2 Передача ссылок на объекты
- •4.9.3 Возврат ссылок
- •4.9.4 Независимые ссылки
- •4.9.5 Использование ссылок для перегрузки унарных операторов
- •4.10 Перегрузка оператора []
- •4.11 Создание функций преобразования типов
- •Глава 5. Наследование, виртуальные функции и полиморфизм
- •5.1 Наследование и спецификаторы доступа
- •5.1.1 Спецификаторы доступа
- •5.1.2 Спецификатор доступа при наследовании базового класса
- •5.1.3 Дополнительная спецификация доступа при наследовании
- •5.2 Конструкторы и деструкторы производных классов
- •5.3 Множественное наследование
- •5.4 Передача параметров в базовый класс
- •5.5 Указатели и ссылки на производные типы
- •5.6 Ссылки на производные классы
- •5.7 Виртуальные функции
- •5.8 Для чего нужны виртуальные функции?
- •5.9 Чисто виртуальные функции и абстрактные типы
- •5.10 Виртуальный базовый класс
- •5.11 Раннее и позднее связывание
- •Глава 6. Подсистема динамического выделения памяти
- •6.1 Введение в обработку исключений
- •6.1.1 Перехват всех исключений
- •6.2 Работа с памятью с помощью new и delete
- •6.3 Размещение объектов
- •6.4 Перегрузка new u delete
- •7.1.1 Потоки
- •7.3 Создание собственных операторов вставки и извлечения
- •7.3.1 Создание операторов вставки
- •7.3.2 Перегрузка операторов извлечения
- •7.4 Форматирование ввода/вывода
- •7.4.1 Форматирование с помощью функций-членов класса ios
- •7.4.2 Использование манипуляторов
- •7.5 Создание собственных функций-манипуляторов
- •7.5.1 Создание манипуляторов без параметров
- •7.5.2 Создание манипуляторов с параметрами
- •7.6 Файловый ввод/вывод
- •7.6.1 Открытие и закрытие файлов
- •7.6.2 Чтение и запись в текстовые файлы
- •7.6.3 Двоичный ввод/вывод
- •7.6.4 Определение конца файла
- •7.6.5 Произвольный доступ
- •Глава 8. Ввод/вывод в массивы
- •8.1 Классы ввода/вывода в массивы
- •8.2 Создание потока вывода
- •8.3 Ввод из массива
- •8.4 Использование функций-членов класса ios
- •8.5 Потоки ввода/вывода в массивы
- •8.6 Произвольный доступ в массив
- •8.7 Использование динамических массивов
- •8.8 Манипуляторы и ввод/вывод в массив
- •8.9 Собственные операторы извлечения и вставки
- •8.10 Форматирование на основе массивов
- •Глава 9. Шаблоны и библиотека stl
- •9.1 Функции-шаблоны
- •9.2 Функции с двумя типами-шаблонами
- •9.3 Ограничения на функции-шаблоны
- •9.4 Классы-шаблоны
- •9.5 Пример с двумя типами-шаблонами
- •9.6 Обзор библиотеки stl
- •9.7 Класс vector
- •9.7 Класс string
- •9.8 Класс list
2.5 Конструкторы и деструкторы
Перед использованием объекта может потребоваться инициализировать некоторые его данные. Для примера рассмотрим класс queue, определенный выше в этой главе. Перед тем как использовать queue, необходимо присвоить переменным r и s значения 0, используя функцию init(). Поскольку требование инициализации является чрезвычайно распространенным, то C++ позволяет производить инициализацию объектов во время их создания. Такая автоматическая инициализация выполняется с помощью функции, которая называется конструктором.
Функция-конструктор, являющаяся членом класса и имеющая имя, совпадающее с именем класса, представляет собой специальный тип функции. В качестве примера ниже показано, как выглядит класс queue, преобразованный таким образом, чтобы использовать для инициализации конструктор:
class queue
{
int q[100];
int s, r;
public:
queue(); // конструктор
void put(int i);
int get();
};
Обратим внимание, что конструктор queue() не имеет типа возвращаемого значения. В C++ функции-конструкторы не могут возвращать значений.
Код, реализующий функцию queue(), выглядит следующим образом:
queue::queue()
{
s = r = 0;
cout << "Queue initialized.\n";
}
Обратим внимание, что выводимое сообщение «queue initialized» служит для иллюстрации работы конструктора. В обычной практике конструкторы не занимаются выводом или вводом данных. Они служат для инициализации.
Конструктор объекта вызывается автоматически при создании объекта. Это означает, что он вызывается тогда, когда происходит объявление объекта. В этом заключается важнейшее различие между объявлениями в языке Си и в C++. В С объявления переменных, попросту говоря, являются пассивными и в большинстве случаев выполняются во время компиляции. Иными словами, в языке С объявления переменных не являются исполняемыми инструкциями. В отличие от этого в C++ объявления переменных служат активными инструкциями, исполняемыми по существу во время работы программы. Одна из причин этого заключается в том, что объявление объекта может требовать вызова конструктора, то есть вызывать выполнение функции. Хотя это различие может показаться едва уловимым и носить больше академический характер, как будет видно далее, оно может оказывать существенное влияние на инициализацию переменных.
При инициализации глобальных или статических объектов конструктор вызывается только один раз. Для локальных объектов конструктор вызывается всякий раз, когда управление доходит до объявления объекта.
Дополнением конструктора является деструктор. Во многих случаях перед уничтожением объекта необходимо выполнить определенные действия. Локальные объекты создаются при входе в соответствующий блок программы и разрушаются при выходе из него. Глобальные объекты уничтожаются при завершении работы программы. Имеется много причин тому, чтобы существовал деструктор. Например, может потребоваться освободить память, которая была ранее выделена. В C++ за дезактивацию отвечает деструктор. Он имеет то же самое имя, что и конструктор, только к нему добавлен значок ~. Ниже представлен вариант класса queue, использующий конструктор и деструктор. (Следует иметь в виду, что класс queue не нуждается в деструкторе, поэтому ниже он приведен только для иллюстрации.)
class queue
{
int q[100];
int s, r;
public:
queue(); // конструктор
~queue(); // деструктор
void put(int i);
int get();
};
queue::queue()
{
s = r = 0;
cout << "Queue initialized.\n";
}
queue::~queue()
{
cout << "Queue destroyed.\n";
}
void queue::put(int i)
{
if(s == 100)
{
cout << "Queue is full.\n";
return;
}
q[s++] = i;
}
int queue::get()
{
if(r == s)
{
cout << "Queue underflow.\n";
return 0;
}
return q[r++];
}
Для того чтобы продемонстрировать работу конструктора и деструктора, ниже представлена новая версия функции main():
int main()
{
queue a, b; // создание двух объектов типа queue
a.put(10); a.put(20);
b.put(19); b.put(1);
cout << a.get() << " ";
cout << a.get() << " ";
cout << b.get() << " ";
cout << b.get() << "\n";
return 0;
}
Эта программа выводит на экран следующий текст:
Queue initialized.
Queue initialized.
10 20 19 1
Queue destroyed.
Queue destroyed.
2.6 Ключевые слова языка С++
Borland C++ включает в себя все ключевые слова, определенные в языке С, и добавляет к ним ряд новых ключевых слов, показанных в таблице 2.1. Нельзя использовать ключевые слова в качестве имен переменных или функций.