欢迎访问 生活随笔!

生活随笔

当前位置: 首页 >

构造函数和析构函数的调用过程

发布时间:2025/10/17 24 豆豆
生活随笔 收集整理的这篇文章主要介绍了 构造函数和析构函数的调用过程 小编觉得挺不错的,现在分享给大家,帮大家做个参考.
下面代码的输出是什么?(D) class A { public: A() { } ~A() { cout<<"~A"<<endl; } }; class B:public A { public: B(A &a):_a(a) { } ~B() { cout<<"~B"<<endl; } private: A _a; }; int main(void) { A a; //很简单,定义a的时候调用了一次构造函数 B b(a); }A、~B
B、~B ~A
C、~B ~A ~A

D、~B ~A ~A ~A



been:
B(A &a):_a(a)
这个引用也是值得注意的,这里提醒大家一下,去掉引用,第一个析构是是~A


灵灵:
下面以例子说明参数为类对象,是否有初始化列表时构造与析构函数的执行顺序:

#include <iostream> using namespace std;class A { public: A(){ cout<<"A"<<endl; }A(const A& other){ cout<<"copy A"<<endl;}~A() { cout<<"~A"<<endl; } }; class B:public A {public:B(A a):_a(a) // B(A &a):_a(a) 会有完全不同的结果{cout<<"B"<<endl;}~B() { cout<<"~B"<<endl; } private: A _a; };void main(void) {A a;B b(a);return;}运行结果:A //A a 创建对象a执行A类的构造copy A //B b(a) 传参的时候利用A类的复制构造A //创建对象B调用基类A的构造copy A //使用初始化列表初始化成员_a利用A类的复制构造B //调用自己的构造~A //析构参数~B //析构自身~A //析构B类成员~A //再析构基类的~A //析构 对象aclass A { public: A(){ cout<<"A"<<endl; }A(const A& other){ cout<<"copy A"<<endl;}~A() { cout<<"~A"<<endl; } }; class B:public A {public:B(A a) //若此处换为:B(A &a),则不调用构造函数{cout<<"B"<<endl;}~B() { cout<<"~B"<<endl; } private: A _a; };void main(void) {A a; B b(a);return;} 运行结果:A <span style="font-family: Arial, Helvetica, sans-serif;">//A a 创建对象a执行A类的构造</span>copy A //B b(a) 传参的时候利用A类的复制构造A //创建对象B调用基类A的构造A //初始化B类的成员执行A类的构造B //调用自己的构造~A //析构参数~B //析构自身~A //析构B类成员~A //再析构基类的~A //析构 对象a


vzhuzhu:
对于构造函数:基类构造函数 > 子类成员变量构造函数 > 子类构造函数
对于析构函数:子类析构函数 > 子类成员变量析构函数 > 基类析构函数
可以看出构造函数的调用过程和析构函数的调用过程正好相反。



水泽渊:
在vs上运行之后发现,输出顺序确实如@Aesthetic92所说,然而@赖聪林说的也没有错,可是@赖聪林举的例子并没有用到拷贝构造函数。
原题-----------------------------------------------------------------------------

class A { public: A() { cout<<"A"<<endl; } ~A() { cout<<"~A"<<endl; } }; class B:public A { public: B(A &a):_a(a) { cout<<"B"<<endl; } ~B() { cout<<"~B"<<endl; }private: A _a; }; void main(void) { A a; B b(a); } // 结果为 A A B ~B ~A ~A ~A
加上拷贝构造函数---------------------------------------------------------------------- <pre name="code" class="cpp"> class A { public: A(){ cout<<"A"<<endl; } A(const A& other){ cout<<"copy A"<<endl;} ~A() { cout<<"~A"<<endl; } }; class B:public A {public:B(A &a):_a(a) {cout<<"B"<<endl; } ~B() { cout<<"~B"<<endl; } private: A _a; }; void main(void) {A a; B b(a);} //结果显示 A A copy A B ~B ~A ~A ~A
修改后---------------------------------------------------------------------------------- class A {public: A() { cout<<"A"<<endl; } A(const A& other){ cout<<"copy A"<<endl;} ~A() { cout<<"~A"<<endl; } };class B:public A {public:B(A &a) { cout<<"B"<<endl; } ~B() { cout<<"~B"<<endl; }private: A _a; };voidmain(void){ A a; B b(a);} //结果为 A A A B ~B ~A ~A ~A


Aesthetic92:
答案:选D
答案解析:答案看起来可能比较怪,其实给默认构造函数补上输出,然后再在基类里写个复制构造函数,这样结果就很明朗了;
首先 A a;这个调用A的默认构造函数,
B b(a); 因为A &a,形参为引用,不需要调用基类复制构造函数(其实基类也没写);_a(a)首先创建对象_a,调用基类A的默认构造函数,然后调用基类复制构造函数(测试的时候可以写出来),把a对象赋给_a,结束之后调用B的析构函数,输出~B;然后调用基类A的析构函数撤销复制构造函数,输出~A;调用基类A的析构函数撤销_a,输出~A;最后调用基类A的析构函数撤销一开始创建的A a,输出~A



kuring:
要想搞明白该问题,需要理解基类构造析构函数、子类构造析构函数和子类成员变量构造析构函数的调用顺序。
对于构造函数:基类构造函数 > 子类成员变量构造函数 > 子类构造函数
对于析构函数:子类析构函数 > 子类成员变量析构函数 > 基类析构函数
可以看出构造函数的调用过程和析构函数的调用过程正好相反。

main函数中首先构造变量a,然后是b。在构造b时首先调用b的基类A的构造函数,然后调用b中成员变量_a的构造函数,最后调用b的构造函数。
main函数调用结束返回时,变量的释放顺序跟变量的构造顺序正好相反。首先释放变量b,然后是变量a。
在释放变量b时,首先调用b的析构函数,然后析构变量b的成员_a,析构_a时调用_a的析构函数。再调用b的基类的析构函数。
然后是释放变量a,调用a的析构函数。

本例子中应该将A的析构函数更改为virtual的,防止使用多态机制时出现子类对象无法释放的情况,本例子中没有用到多态机制,不存在该问题。



赖聪林:

# include <iostream> using namespace std; class A { public: A() { cout<<"create A"<<endl; } A(const A& other){ cout<<"copy A"<<endl;} //复制构造函数~A() { cout<<"~A"<<endl; } }; class C { public:C() { cout<<"create C"<<endl; } C(const A& other){ cout<<"copy C"<<endl;} //复制构造函数~C() { cout<<"~C"<<endl; } }; class B:public A { public: B(){ cout<<"create B"<<endl;} ~B() { cout<<"~B"<<endl; } private: C _a; }; int main(void) {B b; cout<<"------------------------"<<endl; }//上面的输出结果为 create A create C create B ------------------------ ~B ~C ~A
我们可以看到,这个地方先是调用parent class的构造函数,然后对成员变量C类型的构造函数,然后再最后执行B类型的构造函数。
析构的过程就是上面的过程反过来。

所以Aesthetic92的解释有一部分不是很准确。我认为。

更加准确的说明应该是,
最开始析构b,~B,这个是没有争议的。
接着是析构b的成员变量_a,所以是~A
接着是b的parent class(基类)的~A
最后才是a的析构~A
不过为了理解这道题,我感觉配上我的例子更好理解一点,原题的成员变量和基类都是相同的类型,比较难以辨认。

总结

以上是生活随笔为你收集整理的构造函数和析构函数的调用过程的全部内容,希望文章能够帮你解决所遇到的问题。

如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。