- •1. Дополнения к с
- •1.1. Комментарии
- •1.2. Ключевые слова
- •1.3. Константы
- •1.4. Блочные объявления
- •1.5. Ссылки
- •1.6. Новая роль имён перечислений, структур и объединений
- •1.7. Распределение памяти
- •1.8. Встраиваемые функции
- •1.9. Перегрузка функций
- •1.10. Задание для параметров функции значений по умолчанию
- •1.11. Дополнительные операции для доступа к данным
- •1.12. Предопределённые потоки ввода-вывода
- •2.1. Инкапсуляция
- •2.2. Разграничение доступа (скрытие данных и методов)
- •2.3. Друзья классов
- •2.4. Конструкторы и деструкторы
- •2.5. Конструктор по умолчанию
- •2.6. Конструктор копирования
- •2.7. Несколько слов о деструкторах
- •2.8. Перегрузка операций
- •3.1. Наследование
- •3.2. Виртуальные функции –полиморфизм
- •3.3. Шаблоны
2.4. Конструкторы и деструкторы
Среди всех методов любого класса выделяются два, которые определяют, каким образом объекты класса создаются, инициализируются, копируются и разрушаются. Речь идет о конструкторах (constructor) идеструкторах (destructor), которые наряду с характеристиками обычных методов обладают и некоторыми уникальными свойствами:
– конструктор всегда имеет то же имя, что и сам класс; это же относится и к деструктору, которому, однако, предшествует символ ~ (тильда);
– не имеют объявлений о типе возвращаемых значений (даже void);
– не могут быть унаследованы, хотя производный класс может вызывать конструкторы и деструкторы базового класса;
– конструкторы, как и большинство функций С++, могут иметь аргументы по умолчанию или использовать списки инициализации элементов;
– деструкторы могут иметь атрибут virtual, а конструкторы нет;
– нельзя работать с их адресами;
– если конструкторы или деструкторы не были определены явно, они генерируются компилятором;
– конструктор нельзя вызывать как обычную функцию; вызов деструктора возможен с полностью уточнённым именем;
– при определении и разрушении объектов вызов конструкторов и деструкторов осуществляется автоматически;
– конструкторы и деструкторы, при необходимости выделения объекту памяти, могут выполнять явные вызовы операций new и delete.
Прежде чем переходить к более подробному знакомству с этими специальными методами классов, рассмотрим правила, по которым происходит создание/уничтожение объектов:
– конструкторы и деструкторы автоматически запускаются всякий раз при создании и разрушении объектов;
– глобальные и локальные статические объекты создаются в начале выполнения программы – до того, как управление попадает в функцию main (или WinMain). Уничтожение таких объектов происходит в момент завершения программы в результате возврата из функции main (WinMain);
– локальные объекты создаются, когда программа встречает их определение, и уничтожаются при выходе из функции;
– конструктор объекта, память которому выделяется в куче (посредством операции new), вызывается автоматически при вызове new; такой объект разрушается при явной передаче объекта в оператор delete.
Примечание
Для объектов, память под которые выделяется вызовом malloc (или аналогичной функции), конструктор не вызывается вообще, поскольку в этом случае функция просто не знает, какой конструктор надо запустить (эта функция не принимает никакой информации о типе).
Рассмотрим простой пример, для которого воспользуемся классической функцией main, чтобы избежать дополнительных действий, необходимых для Windows-приложений:
Пример 2.2
#include <stdio.h>
#include <string.h>
// Объявляем класс
class sample {
private: // К этим данным доступ возможен только посредством методов класса
char * StrName;
public: // К этим данным доступ возможен из любого места программы
// Определяем простой конструктор
Sample (char * str) {
strName = new char[strlen(str) + 1];
strcpy(strName, str);
printf(“Entry in constructor for %s\n”, strName);
}
// Определяем деструктор
~Sample( ){
printf(“Entry in destructor for %s\n”, strName);
delete strName;
strName = 0;
}
// Определяем первый глобальный объект
Sample global1(“global #1”);
// "Глупая" функция, иллюстрирующая создание автоматического объекта
void Sillyfunc( ) {
// Определяем объект, локальный для данной функции
Sample fnAuto (“automatic function”);
printf(“Function SillyFunc()\n”);
}
int main(int argc, char *argv[])
{
// Определяем первый локальный объект
Sample auto1(“automatic #1”);
printf(“Begin main()\n”);
SillyFunc( );
// Определяем второй локальный объект
Sample auto2(“automatic #2”);
printf(“Continue main()\n”);
return o;
}
// Определяем второй глобальный объект
Sample global2(“global #2”);
Результат выполнения этой программы будет выглядеть следующим образом:
Entry in constructor for global #1
Entry in constructor for global #2
Entry in constructor for autimatic #1
Begin main()
Entry in constructor for automatic function
Function SillyFunk()
Entry in destructor for automatic function
Entry in constructor for autimatic #2
Continue main()
Entry in destructor for automatic #2
Entry in destructor for automatic #1
Entry in destructor for global #2
Entry in destructor for global #1
Обратите внимание на последовательность создания и разрушения глобальных и автоматических объектов.
Пойдём дальше. Конструкторы подчиняются тем же правилам перегрузки, что и любые другие функции. Один и тот же класс может иметь несколько конструкторов, если каждый из них имеет свой собственный список аргументов. При определении объекта будет запущен тот конструктор, с которым совпадает заданный список аргументов.
Примечание
Единственным ограничением на аргументы конструктора является то, что в качестве их нельзя использовать объект того же класса. Вместо этого можно использовать ссылку на объект.
Некоторые конструкторы играют особую роль.