欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

理解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;
}
输出结果:
理解C++存在继承和组合的对象构造函数调用顺序(转载)

小结:
可以看到:
1)带有继承以及组合的类的构造函数顺序是: 父类的构造函数->组合成员对象的构造函数 ->子类自己的构造函数;
2)类成原变量的空间分配及初始化是在调用自己构造函数之前进行的,他们的声明初始化顺序由声明顺序决定,这个点在构造函数的初始化列表中的面试考点经常考到,注意,不是由其出现在初始化列表中的顺序决定,而是由其在类中声明的顺序决定其初始化的顺序;
3)对象在析构的时候,析构函数的调用顺序与构造函数的执行顺序相反,这个很容易理解,因为常规创建对象比如ClassA a;是在栈里创建对象的,程序结束或离开了对象的作用域,自然要清空那个原来的栈,栈的弹出都是从栈顶里面一个个出栈的,但要注意通过new来创建的对象是在堆中创建的,所以对于new出来的对象是在delete的时候才会调用其析构函数,否则不会调用析构函数,即使其离开了作用域或者程序结束都不会调用其析构函数;


相关标签: cpp