码迷,mamicode.com
首页 > 编程语言 > 详细

【C++札记】C++构造及析构函数执行顺序

时间:2020-11-23 12:42:12      阅读:17      评论:0      收藏:0      [点我收藏+]

标签:遍历   har   mes   end   成员   argc   视频分享   文章   服务器   

前不久,一个朋友面腾讯社招的后台开发岗,和他聊了聊,他说腾讯的一面还是比较重基础的,C++,操作系统,网络、算法这块问的比较多,即便是社招。其中就有一个C++牵涉到虚拟继承时其构造和析构顺序的题目,这个平时也不太注意,因此也真难住了不少面试者,我那位朋友就是其一,因此有必要总结下。

在C++中,当创建一个类对象时,编译器是会自动调用一个叫构造函数的东西的,我们知道,C++类与类之间很多情况下是有关联的,比如继承,组合等等,读懂UML类图(请戳我)一文中有描述该主题。本文主要通过实例总结各种情况下的构造与析构顺序。

继承

场景:B类继承两个父类A和C,每个类的构造函数和析构函数很简单,就是打印对应的函数名,以便观察构造及析构函数执行顺序。

#include <iostream>

using namespace std;

class A
{    
    public:        
        A(){cout << "A()" << endl;}       
        ~A(){cout << "~A()" << endl;}
};

class C
{    
    public:        
        C(){cout << "C()" << endl;}        
        ~C(){cout << "~C()" << endl;}
};

class B: public A, public C
{    
    public:        
        B(){cout << "B()" << endl;}        
        ~B(){cout << "~B()" << endl;}
};

int main(int argc, char const *argv[])
{    
    B b;    
    return 0;
}
bogon:dataStructure lizhong$ ./t
A()
C()
B()
~B()
~C()
~A()

通过运行结果可以看出:创造一个子类对象时,先执行父类的构造函数,再执行自身的构造函数,如果子类继承多个父类,则按照继承的顺序从左到右调用父类构造函数(本例先构造A,再构造C),析构的顺序与构造的顺序相反。

我们还知道还有一种继承叫做虚拟继承,看看这种情况下的构造与析构又是怎样的顺序。

#include <iostream>

using namespace std;

class A
{    
    public:        
        A(){cout << "A()" << endl;}       
        ~A(){cout << "~A()" << endl;}
};

class C
{    
    public:        
        C(){cout << "C()" << endl;}        
        ~C(){cout << "~C()" << endl;}
};

class B: public A, public C
{    
    public:        
        B(){cout << "B()" << endl;}        
        ~B(){cout << "~B()" << endl;}
};

int main(int argc, char const *argv[])
{    
    B b;    
    return 0;
}
bogon:dataStructure lizhong$ ./t
C()
A()
B()
~B()
~A()
~C()

可以看出:虚拟继承和一般的继承构造和析构的顺序还是有点不一样,父类的构造顺序发生了改变,虚拟继承的C构造函数先被执行,然后是A。最后是自身的构造函数被调用,析构的顺序与构造的顺序相反。

成员包含其它类对象成员

场景:B类含有A类对象和C类对象的成员,且在B类中,其成员声明顺序是先声明c,再声明a。看看创造B类对象时,构造函数和析构函数的执行顺序是怎样的。

#include <iostream>

using namespace std;

class A
{    
    public:        
        A(){cout << "A()" << endl;}       
        ~A(){cout << "~A()" << endl;}
};

class C
{    
    public:        
        C(){cout << "C()" << endl;}        
        ~C(){cout << "~C()" << endl;}
};

class B
{    
    public:        
        B():a(A()), c(C()) {cout << "B()" << endl;}        
        ~B(){cout << "~B()" << endl;}
        C c;  
        A a;
};

int main(int argc, char const *argv[])
{    
    B b;    
    return 0;
}
bogon:dataStructure lizhong$ ./t
C()
A()
B()
~B()
~A()
~C()

运行结果可以看出:创造一个B类对象b时,先执行其成员对象所属类的构造函数,再执行自身的构造函数,如果有多个类对象成员,则按照声明的顺序调用对应类的构造函数(本例先构造C类对象c,再构造A类对象a),析构的顺序与构造的顺序相反。

即有继承又包含类对象成员

场景:B类继承两个父类A和C,并且B类有一个X类的对象成员,观察构造及析构函数执行顺序。

#include <iostream>
using namespace std;

class A
{
    public:
        A(){cout << "A()" << endl;}
        ~A(){cout << "~A()" << endl;}
};

class C
{
    public:
        C(){cout << "C()" << endl;}
        ~C(){cout << "~C()" << endl;}
};

class X
{
    public:
        X(){cout << "X()" << endl;}
        ~X(){cout << "~X()" << endl;}
};

class B: public A, public  C
{
    public:
        B(){cout << "B()" << endl;}
        ~B(){cout << "~B()" << endl;}
        X x;
};

int main(int argc, char const *argv[])
{
    B b;
    return 0;
}
bogon:dataStructure lizhong$ ./t
A()
C()
X()
B()
~B()
~X()
~C()
~A()

运行结果可以看出:类在构造的时候会先从左到右调用父类的构造函数,然后调用类对象成员构造函数,最后调用自身构造函数。析构的顺序与构造的顺序相反。

推荐阅读:

精心整理 | 历史干货文章目录
【福利】自己搜集的网上精品课程视频分享(上)
【数据结构与算法】 通俗易懂讲解 二叉树遍历
【数据结构与算法】 通俗易懂讲解 二叉搜索树

专注服务器后台技术栈知识总结分享

欢迎关注交流共同进步

技术图片

码农有道 coding

码农有道,为您提供通俗易懂的技术文章,让技术变的更简单!

【C++札记】C++构造及析构函数执行顺序

标签:遍历   har   mes   end   成员   argc   视频分享   文章   服务器   

原文地址:https://blog.51cto.com/15006953/2552126

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!