1. 类对象大小受三方面的影响:1)virtual base或virtual func带来的负担;2)是否EBO;3)alignment(sizeof大全)。
2. virtual base class表示“只有一个单一而被共享的实体”,而无论出现在继承体系中多少次。
3. c++并不强制“base class subobject的内存排列次序”和“不同存取级别的类中的数据成员”的排列次序。
4. static数据成员会放到global data segment中,并不会影响到单独某一个object的大小。
5. 数据成员类型的绑定、成员函数指针请参看代码部分。关于成员函数指针,要对对象的sizeof非常了解才能懂。
6. 由X的对象x和指针pt存取成员变量m,何时会有什么重大差别?当m是从X的virtual基类派生而来时。
7. 内存中,基类出现在子类前面,但virtual基类会在整个布局的最后面;如果有多个virtual基类,以声明序排列。
8. 继承对类的数据成员的影响(详细请看系列的附录部分):
a) 简单无多态的继承。不会增加内存空间以及存取上的额外负担。C++语言保证:出现在子类中的基类子对象(base class subobject)要保持其原样完整性”,即:任何时间取出“基类子对象”都是一个完整的整体。要注意对齐问题。
b) 加上多态(有虚函数)
Ø 开销:1)vtbl(含typeid);2)加入vptr;改造3)构造函数和4)析构函数,以处理vptr。VC把vptr放到对象的最前面(如果有virtual base class的话,vptr会在offset指针之后),即使基类没有virtual函数而只有子类有。
Ø 子类与第一个父共享同一个vptr,有第二基类会增加vptr。子类增加新或修改virtual函数会更新对应vtbl的内容。
c) 多重继承:其问题主要出现在派生类对象与其第二或后面的基类对象之间的转换,因为这样会涉及到指针的offset。
d) 虚拟继承即类含有N个virtual基类
Ø 代表着它可以被切割为两部分:不变部分(放前面)和共享部分(放后面)。
Ø 不变部分中的数据,不论后继如何变化,其offset总是固定的;而共享部分,表示的是virtual基类的子对象,它的offset会因为派生层次的增加(无论在最底层还是最高层增加)而有变化,因为它总是在整个类对象的最后面。
Ø 派生类中会安排指向virtual基类的offset指针,与访问virtual基类成员,需要首先进行offset进行偏移定位。
9. 关于对齐对sizeof的影响,只有:1)所有的“基类子对象”全是char;或2)virtual base全是char;这两种情况才可能出现奇数size(19,23等),其他情况肯定都是被对齐到int、*(比如vptr)、double等的长度。
一些实验代码: