首先,我们来看一段代码:
#include<iostream>
using namespace std;
class A
{
public:
A()
{
cout << "A's constructor." << endl;
}
~A()
{
cout << "A's destructor." << endl;
}
};
class B
{
public:
B()
{
cout << "B's constructor." << endl;
}
~B()
{
cout << "B's destructor." << endl;
}
};
class C
{
private:
B bInC;
public:
C()
{
cout << "C's constructor." << endl;
}
~C()
{
cout << "C's destructor." << endl;
}
A aInC;
};
class D:public C
{
public:
D()
{
cout << "D's constructor." << endl;
}
~D()
{
cout << "D's destructor." << endl;
}
A aInD;
private:
B bInD;
};
int main(void) {
D d;
return 0;
}
那么,这段程序执行后,输出什么呢?
B's constructor.
A's constructor.
C's constructor.
A's constructor.
B's constructor.
D's constructor.
D's destructor.
B's destructor.
A's destructor.
C's destructor.
A's destructor.
B's destructor.
分析如下:
(1)存在继承关系时,先执行父类的构造函数,再执行子类的构造函数;
(2)当一个类中含有对象成员时,在启动本类的构造函数之前,先分配对象空间,按对象成员的声明顺序执行他们各自的构造函数,再继续执行本类的构造函数;
(3)对于非静态的局部对象,他们的析构函数的执行顺序与构造函数相反。
在本程序中:
(1)执行main(),需要创建一个对象d,所以,需要执行D的构造函数。而D继承自C,所以先要执行C的构造函数;
(2)而在C中存在对象成员bInC和aInC,所以,在C的构造函数执行之前,先按声明顺序执行B和A的构造函数,然后执行C的构造函数;
(3)轮到构造d了,但是D中有对象成员aInD和bInD,所以,在D的构造函数执行之前,先按声明顺序执行A和B的构造函数,最后,执行D的构造函数;
(4)以上所有对象的析构函数以与构造函数的执行顺序相反的顺序执行。