При использовании производных классов важно представлять себе, каким образом и когда исполняются конструкторы и деструкторы базового и производного классов. Начнем рассмотрение с конструкторов.
Как базовый класс, так и производный класс могут иметь конструкторы. (В многоуровневой иерархии классов каждый из классов может иметь конструкторы, но мы начинаем с наиболее простого случая.) Когда базовый класс имеет конструктор, этот конструктор исполняется перед конструктором производного класса. Например, рассмотрим следующую короткую программу:
#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
ПАМЯТКА: Следует запомнить, что конструкторы вызываются в том порядке, в котором классы выводились один из другого. Порядок вызова деструкторов обратный. |