理解C++存在继承和组合的对象构造函数调用顺序(转载)
程序员文章站
2022-04-25 15:19:39
...
这段时间在学习C++的一些基础知识,然后发现自己对继承类里面的一些构造函数、析构函数的调用顺序有点忘了,然后找到一个比较好的博客,转载过来做一个备份。以下原文(https://blog.csdn.net/u013777351/article/details/48153253):
#include <iostream>
using namespace std;
class A {
public:
A() {cout << "A" ;}
~A() {cout << "~A" ;}
};
class B {
public:
B() {cout << "B" ;}
~B() {cout << "~B";}
private:
A a;
};
class C : public A {
public:
C() {cout << "C" ;}
~C() {cout << "~C";}
private:
B b;
A a;
};
int main()
{
cout << "=======================================\n";
cout << "A类对象的构造过程: ";
A a;
cout << "\n======================================\n\n";
cout << "B类对象的构造过程: " ;
B b;
cout << "\n=======================================\n\n";
cout << "C类对象的构造过程: ";
C *p = new C();
// 动态申请的内存别忘了释放,否则不会调用析构函数,任何时候delete 空指针也不会错
delete p;
// 注意,如果这里没有刷新缓冲区的话最后的那三个析构函数被执行,但数据留在缓冲区中,没有输出
// 因为析构函数里面也没有cout<<endl;之类的刷新缓冲区,没有刷新缓冲区的的输出结果如图二
cout << "\n=======================================\n";
return 0;
}
输出结果:小结:
可以看到:
1)带有继承以及组合的类的构造函数顺序是: 父类的构造函数->组合成员对象的构造函数 ->子类自己的构造函数;
2)类成原变量的空间分配及初始化是在调用自己构造函数之前进行的,他们的声明初始化顺序由声明顺序决定,这个点在构造函数的初始化列表中的面试考点经常考到,注意,不是由其出现在初始化列表中的顺序决定,而是由其在类中声明的顺序决定其初始化的顺序;
3)对象在析构的时候,析构函数的调用顺序与构造函数的执行顺序相反,这个很容易理解,因为常规创建对象比如ClassA a;是在栈里创建对象的,程序结束或离开了对象的作用域,自然要清空那个原来的栈,栈的弹出都是从栈顶里面一个个出栈的,但要注意通过new来创建的对象是在堆中创建的,所以对于new出来的对象是在delete的时候才会调用其析构函数,否则不会调用析构函数,即使其离开了作用域或者程序结束都不会调用其析构函数;
上一篇: q1 迭代器报错
下一篇: CPP知识点整理(三)