Шаг 12 - Конструкторы и деструкторы

Если Вы хотя бы в какой-то мере пытались разобраться в работе ООП, Вы обязательно натыкались на такие понятия, как Конструкторы и Деструкторы. Впрочем эти структуры могут иметь и другое название, к примеру, как в Visual Basic. Но это не имеет принципиального значения. Так что же означают эти понятия ? Я рассмотрю общие правила применения конструкторов и деструкторов в С++.

К сожалению, а может быть и к счастью, понятия в ООП тесно взаимосвязаны между собой. Невозможно объяснить одно понятие отдельно от других. В ООП есть понятие области видимости объекта, переменной. Это понятие я возможно затрону по подробнее, но не сейчас. Переводя это понятие на нормальный человечекий язык - это время жизни чего(или кого)-либо. К примеру, человек зачат (извиняюсь за такие интимные подробности), рождается, живет, учится, работает, что-то делает и, к сожалению, умирает, его тело превращается в прах. Аналогично и с объектами. Проводя дальнейшую аналогию, конструктор работает на отрезке времени с момента зачатия до момента рождения. На этом этапе происходит формирование скелета объекта (инициализация). Также можно провести аналогию с таким детским конструктором как Лего. У вас есть кубики или части определенной конфигурации и из них собираете какую-то конструкцию (фигуру, замок и т.д.). Таким образом, конструктор отвечает за начальное формирование(инициализацию) объекта на этапе его создания.

Очень часто конструктор заимствуется из родительского класса, но далеко не всегда.

В языке С++ конструктор имеет тоже самое имя, что и имя класса и не может иметь какой-либо определенный возвращаемый тип, поскольку имеет заранее определенный возвращаемый тип - указатель на инициализируемый объект.

Следует отметить, что функция конструктора запускается на этапе описания (декларирования) объекта. Т.е. декларирование объекта MyObject класса CMyObject следующей строкой

  CMyObject  MyObject;

приводит к вызову конструктора этого класса для данного объекта. Казалось бы, мы еще ничего не сделали с объектом, только описали, а какая-то функция уже выполняется !

Для тех, кто собирается работать с языком С++ на заметку: Если декларирование объекта произведено до выполнения основного модуля, то функция конструктора будет выполнена до выполнения этого модуля.

Продолжая аналогию с челоческой жизнью, Деструктор работает на отрезке времени, когда человек уже умер, но еще не превратился в прах. Т.е. вернуть, к сожалению, его уже нельзя, но сделать какой-то завершающий аккорд еще можно. Чаще всего этот этап используется для "зализывания ран" - корректного освобождения блоков памяти, выделенных при работе с этим объектом. Дело в том, что при "умирании" объекта, "умирают" и ссылки на все блоки памяти, которые были выделены объекту в процессе работы. Если мы не освободим выделенные объекту блоки памяти, то никто и не подумает их освобождать. В результате получится, что мы храним данные, которые нам уже абсолютно не нужны и мы даже не имеем к ним доступа ! В больших программах это может привести не только к краху самой программы, но и к замедлению работы или даже зависанию операционной системы. Применение деструктора в этом случае помогает избежать утечек памяти(memory leaks).

Итак, когда объект уже "представился" и готов уйти в небытие, автоматически вызывается деструктор, естесственно, если он существует.

В языке С++ Деструктор имеет тоже имя, что и имя класса с предшествующей ему тильдой. Деструктор не имеет никакого возвращаемого типа.

Ниже я привел пример класса с Конструктором и Деструктором в С++. Этот код не имеет никакого реального смысла, но наглядно показывает как можно использовать конструктор и деструктор.

сlass CMyClass
{
  public:
    CMyClass();  // Конструктор класса CMyClass
    ~CMyClass();   // Деструктор класса CMyClass
private:
   int MyInt;  // переменная типа integer (целое число)
   int *point; // переменная типа указатель на integer (целое число)
};

CMyClass::CMyClass()  // Конструктор
{
MyInt=10;   // На этапе инициализации объекта класса CMyClass присваиваем 
                    // переменной этого объекта MyInt значение 10

point = new int; // Выделяем блок памяти под целое число, на которое 
                          // будет указывать указатель
*point = 20;      //  Сохраняем в этот выделенный блок памяти число 20
}

CMyClass::~CMyClass()  // Деструктор
{
MyInt=0;   // Объект класса CMyClass уже фактически прекратил существование,
                  // но мы присваиваем переменной класса MyInt значение 0

delete point; // Используем указатель на число для того, чтобы освободить
                    // блок памяти, выделенный под это число.
                    // Если мы этого здесь не сделаем, никто за нас это не сделает
}

И последнее, что хотелось бы отметить, реализация конструкторов и деструкторов в конкретных языках может отличаться или могут существовать какие-либо специфические особенности их реализации. Я сознательно коснулся только общих принципов их работы. Для более полного обзора данных структур конкретного языка программирования лучше всего обращается к описанию его разработчика. К примеру, в языке С++ существует ряд других, не указанных мной, особенностей реализации и автоматического генерирования (при их отстутствии) конструкторов.


Предыдущий Шаг | Оглавление
Автор Valeri Khromov - 5.02.2000