基本语言细节--《深度探索C++对象模型》--(5)Semantics of Construction,Destruction,and Copy-总结点
1.继承体系下的对象构造顺序:
Constuctor可能含有大量的隐藏代码,因为编译器会扩充每一个constructor,一般而言扩充早错大约如下:
(1).记录在成员初始化列表中的数据成员初始化操作会被放在构造函数的本体内,并以成员声明顺序为顺序;
(2).若有成员没有写在初始化列表中,但它又有一个默认的构造函数,则此默认的构造函数必须被调用;
(3).在那之前,如果类对象有虚函数表指针,则它(们(可能有多个))必须被设定初值,指向适当的virtual tables;
(4).在那之前,所有的基类构造函数必须被调用,以基类的声明顺序为顺序(就是在派生类声明时的排列顺序,而与成员初始化列表没有关联)。
A.如果基类被列在成员初始化列表中,则任何显式的参数都应该被传递进去;
B.如果基类有成员没有列入其中,而其又有默认的构造函数,则调用之;
C.如果基类是多重继承下的第二或后继的基类,则this指针必须有所调整;
(5).在那之前,所有的虚基类构造函数必须被调用,从左到右,从最深到最浅:
A.如何类被列于初始化列表中,那么如果有任何显式的参数,都应该被传递过去。若没有列于列表中,而类有一个默认的构造函数,则应该调用之。
B.此外,每一个虚基类的偏移位置,必须在执行期可被存取;
C.如果类对象是最底层的类,其构造函数可能被调用,某些支持这一行为的机制必须被放进来。
2.何时初始化vptr?
在基类构造函数之后,但是在程序员供应的代码或是成员初始化列表中所列成员初始化操作之前!!!
3.建议:不要在任何虚基类中声明数据;
4.析构函数扩展顺序:
类似于构造函数,但是顺序相反!
(1).析构函数的本体首先被执行;
(2).如果类中有成员对象,而其又有析构函数,那么他们会以声明顺序的相反顺序被调用!
(3).如果对象内有vptr,则会被重新设定(即是派生类的部分析构完时执行),使之指向适当的基类的虚函数表;
(4).如果任何直接上层非虚基类有析构函数,则以声明顺序的反序被调用;
(5).如果任何虚基类有析构函数,而且目前这个类是最尾端的类,那么他们会以其原来的构造顺序的反序被调用,进行析构!完成对象的清理工作!
卧浪居士于HUST2013.11.21