编译器间的两个程序扩张操作(只要有一个类声明了一个或多个virtual functions就会如此) :
1. 增加一个virtual function table (vtbl) ,内含每一个有用的virtual function 的地址
2. 一个指向virtual function table 的指针(vptr),安插在每一个class object内
当class object以“相同class的另一个object”作为初始,其内是以所谓的default memberwise initialization手法完成的,也就是把每一个内建的或者派生的data member的值,从某一个object拷贝一份到另外一个object上,不过它并不会拷贝其中的member class object ,而是以递归的方式施行memberwise initialization 。
在下列情况下,为了使程序能够被顺利编译,必须使用一个member initialization list :
当初始化一个reference member 时
当初始化一个const member 时
当调用一个基类 的constructor,而其有一组参数时
当调用一个member class 的 constructor 时,而它拥有一组参数时
member list 中的顺序是由member 中的声明顺序来决定的
编译器会对initialization list 一一处理并可能重新排序,以反映出members 的声明顺序,它会安插一些代码到constructor中,并置于任何explicit user code 之前。
1. 编译器自动加上的额外data members ,用于支持某些语言特性(主要是各种virtual特性)
2. 因为alignment (边界调整)的需要
constructor 可能内含大量的隐藏码,因为编译器会扩展每一个constructor,扩充程度视class的继承体系而定,一般而言编译器所做的扩充操作大约如下:
1. 记录在member initialization list 中的 data member 初始化操作会被放进constructor的函数本体,并以member的声明顺序为顺序
2. 如果有一个member并没有出现在member initialization list 中,但它有一个default constructor,那么该default constructor 必须被调用
3. 在那之前,如果类对象有virtual table pointer(s) ,它(们)必须被设定初值,指向适当的virtual talbe(s)
4. 在那之前,所有上一层的base class constructor 必须被调用,以base class的声明顺序为顺序(与member initialization list中的顺序没有关系)
如果base class 被列于member initialization list 中,那么任何显示指定的参数都应该被传递进去
如果base class 没有被列于member initialization list 中,而它有default constructor(或default memberwise copy constructor ) ,那么就调用之。
如果base class 是多重继承的第二个或后继的base class ,那么this指针必须有所调整。
5.在那之前,所有virtual base class constructors 必须调用,从左到右,从最深到最浅
如果class被列于member initialization list 中,那么如果有任何显示指定的参数,都应该传递过去,若没有列于list中,而class有一个default constructor,亦调用之
此外,class中每一个virtual base class subject 的偏移位置(offset)必须在执行期可被存取
如果class object是最底层的class,其constructor可能被调用;某些用以支持这一行为的机制必须被放进来
vptr的处理:
在base class constructor 调用操作之后,但在程序员供应的代码或是member initialization list 中所列出的members初始化操作之前。
constructor的执行算法如下:
1. 在derived class constructor 中,所有virtual base classes 及上层base class 的constructor会被调用
2. 上述完成之后,对象的vptr 会被初始化,指向相关的virtual tables
3. 如果有member initialization list 的话,将在constructor体内扩展开来,这必须在vptr被设定之后才做,以免有一个virtual member function被调用
4. 最后,执行程序员提供的代码
Template之中,对于一个non-member name的决议结果,是根据这个name使用是否与“用以实例化该template的参数类型”有关而决定的,如果使用互不相关,那么就以“scope of the template declaration” 来决定name,如果其使用互有关联,那么就以“scope of the template instantiation” 来决定name。
一个编译器必须保持两个scope contents:
1. scope of the template declaration :用于专注于一般的template class
2. scope of the template instantiation:用于专注于特定的实例
接口继承和实现继承不同,在public继承下,derived class总是继承base class 的接口。
pure virtual函数只具体制定接口继承。
inpure virtual函数具体指定接口继承及缺省的实现继承。
non-virtual 函数具体指定接口继承以及强制实现继承。
在应用域(application domain),复合意味着has-a(有一个),在实现域(implementation domain),复合意味着is implemented in terms of(根据某物实现出)。
private继承纯粹是一种实现技术,意味implemented in terms of,private继承在软件“设计”层面上没有意义,其意义只及于软件实现层面。
private继承意味is implement in terms of,它通常比复合的级别低,但是当继承类需要访问protected base class的成员,或需要重新定义继承而来的virtual函数时,那么实际是合理的。和复合不同,private继承可以造成empty base最优化,这对致力于“对象尺寸最小化”的程序库开发者而言,可能很重要。