Программирование на C и C++

Онлайн справочник программиста на C и C++

Конструкторы и деструкторы производных классов

При использовании производных классов важно представлять себе, каким образом и когда ис­полняются конструкторы и деструкторы базового и производного классов. Начнем рассмотрение с конструкторов.

Как базовый класс, так и производный класс могут иметь конструкторы. (В многоуровневой иерархии классов каждый из классов может иметь конструкторы, но мы начинаем с наиболее простого случая.) Когда базовый класс имеет конструктор, этот конструктор исполняется перед конструктором производного класса. Например, рассмотрим следующую короткую программу:

#include <iostream.h>
class Base {
public:
Base () {cout << "\nBase created\n";}
};
class D_class1(): public Base {
public:
D_class1() {cout << "D_class1 created\n";}
};
int main()
{
D_class1 d1;
// ничего не делается, но выполняются конструкторы
return 0;
}

Эта программа создает объект типа D_class1. Она выводит на экран следующий текст:

Base created
D_class1 created

Здесь d1 является объектом типа D_class1, производным класса Base. Таким образом, при созда­нии объекта d1 сначала вызывается конструктор Base(), а затем вызывается конструктор D_class1().

Конструкторы вызываются в том же самом порядке, в каком классы следуют один за другим в иерархии классов. Поскольку базовый класс ничего не знает про свои производные классы, то его инициализация может быть отделена от инициализации производных классов и производит­ся до их создания, так что конструктор базового класса вызывается перед вызовом конструктора производного класса.

В противоположность этому деструктор производного класса вызывается перед деструктором базового класса. Причину этого также легко понять. Поскольку уничтожение объекта базового класса влечет за собой уничтожение и объекта производного класса, то деструктор производно­го объекта должен выполняться перед деструктором базового объекта. Следующая программа иллюстрирует порядок, в котором выполняются конструкторы и деструкторы:

#include <iostream.h>
class Base {
public:
Base() {cout << "\nBase created\n";}
~Base() {cout << "Base destroyed\n\n,"; }
};
class D_class1(): public Base {
public:
D_class1() {cout << "D_class1 created\n";}
~D_class1() {cout << "D_class1 destroyed\n "; }
};
int main()
{
D_class1 d1;
cout << " \n";
return 0;
}

Эта программа выдаст следующий текст на экран:

Base created
D_class1 created
D_class1 destroyed
Base destroyed

Производный класс может служить базовым классом для создания следующего производного класса. Когда такое происходит, конструкторы исполняются в порядке наследования, а деструк­торы — в обратном порядке. В качестве примера рассмотрим следующую программу, использую­щую класс D_class2, производный от класса D_ciass1:

#include <iostream.h>
class Base {
public:
Base() {cout << "\nBase created\n";}
~Base() {cout << "Base destroyed\n\n";}
};
class D_class1() : public Base {
public:
D_class1() {cout << "D_class1 created\n";}
~D_class1() {cout << "D_class1 destroyed\n ";}
};
class D_class2: public D_class1 {
public:
D_class2() {cout << "D_class2 created\n";}
~D_class2() {cout << "D_class2 destroyed\n ";}
};
int main()
{
D_class1 d1;
D_class2 d2;
cout << "\n";
return 0;
}

Эта программа выдаст следующий результат:

Base created
D_class1 created
Base created
D_class1 created
D_class2 created
D_class2 destroyed
D_class1 destroyed
Base destroyed
D_class1 destroyed
Base destroyed

ПАМЯТКА: Следует запомнить, что конструкторы вызываются в том порядке, в котором классы выводились один из другого. Порядок вызова деструкторов обратный.