C++复合与继承下的ctor和dtor顺序

C++复合与继承下的ctor和dtor顺序

了解到复合关系与继承关系,我们知道了复合关系下:先构造内部,再构造外部

                  继承关系下:先构造父类,再构造子类


那么在既有复合关系,又有继承关系的情况下,构造与析构的顺序分别是怎样呢,基于这个问题,写一段简单的代码观察。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include<iostream>
using namespace std;

class A {
public:
A() { cout << "A"; }
~A() { cout << "A"; }
};
class B {
public:
B() { cout << "B"; }
~B() { cout << "B"; }
};
class C : public A {
protected:
B b;
public:
C() { cout << "C"; }
~C() { cout << "C"; }
};

int main() {
C * c = new C();
cout << endl;
delete c;
system("pause");
return 0;
}

运行结果如下:

ABC
CBA

可知,在复合关系与继承关系同时存在时,先构造父类,再去构造派生类以及它的内部类,而析构顺序则与构造顺序刚好相反。

补充一下类对象的创建与释放过程:

详细说明:https://blog.csdn.net/m0_37622246/article/details/99681188

类的创建过程

1、从堆栈中分配类所需要的空间。
2、根据需求传递或不传递参数调用构造函数,完成如下任务:

①根据继承表依次调用父类的构造函数。

②根据成员变量的顺序依次调用成员变量的构造函数。

③执行构造函数体中的代码。

注意:执行构造函数的代码是整个构造函数的最后一步,要保证构造函数代码所需要的一切资源和先决条件在该代码执行前已经准备充分,并得到正确的初始化。


类的释放过程

析构函数负责释放在构造函数期间获取的所有资源,它的执行过程:

①先执行析构函数本身代码

②调用成员类的析构函数

③调用父类的析构函数

如果一个类没实现析构函数,编译器会自动生成一个具有析构功能的二进制指令,它负责释放编译器能够看得到的资源(成员变量、类成员、父类成员),这就是缺省析构。

如果类中没有动态资源,也不需要做善后工作,缺省析构就完全够用了,不需要再定义新析构函数。
注意:缺省析构无法释放动态资源(堆内存)。