标签:遍历 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()
运行结果可以看出:类在构造的时候会先从左到右调用父类的构造函数,然后调用类对象成员构造函数,最后调用自身构造函数。析构的顺序与构造的顺序相反。
精心整理 | 历史干货文章目录
【福利】自己搜集的网上精品课程视频分享(上)
【数据结构与算法】 通俗易懂讲解 二叉树遍历
【数据结构与算法】 通俗易懂讲解 二叉搜索树
码农有道,为您提供通俗易懂的技术文章,让技术变的更简单!
标签:遍历 har mes end 成员 argc 视频分享 文章 服务器
原文地址:https://blog.51cto.com/15006953/2552126