一 引导:
(1)类对象的大小和机器、编译器有关。
(2)类对象的大小受到三个因素的影响(除了对象所有的nonstatic data members):
1.语言本身的所造成的额外负担。例如:支持virtual base class时就会导致额外负担。
2.编译器对于特殊情况所提供的优化处理。
3.Alignment的限制。在32机器上通常alignment通常为4字节。
二 Data Member的绑定。
三 Data Member的布局:C++ Standard允许编译器决定布局,所以不同编译器不同。
四 Data Member的存取:
(一)static data member:(直接通过类存取,也可通过对象存取)
(1)static data members可被视为global 变量(但作用域在类中)。
(2)每个static data member只有一个实体,存放在程序的data segment中,每次取用static member,就会被内部转换为对唯一的extern实体的直接操作。从指令的执行观点来看,这是C++中"通过一个指针和通过一个对象来存取member,结论完全相同的"唯一一种情况。
(3)取一个static data member的地址,会得到一个指向其数据类型的指针,而不是一个指向其class member的指针,因为static member并不内涵在一个class object之中。
(4)如果两个class声明同名的static member会导致名称冲突,编译器的做法是暗中对每个static data member编码(name),以获得一个独一无二的程序识别代码。
(二)nonstatic data member:
(1)对一个nonstatic data member的存取操作,编译器需要把class object的起始地址加上data member的偏移量,每一个nonstatic data member的偏移量在编译期即可知道。
五 继承与Data Member:
(一)单一继承没有多态。
(二)单一继承+多态:
1.多态的负担:
*导入一个与类相关的virtual table存放它声明的每一个virtual function。
*每一个类对象都导入一个vptr,提供执行期的链接,使每一个object能够找到相应的virtual table。
*加强constructor,使它能够为vptr设定初值,让它指向class对应的virtual table。
*加强destructor,使它能够撤销"指向class相关virtual table"的vptr。
2.vptr的放置位置:
*通常把vptr放置在base class的尾端。
(三)多重继承:
1.对于一个多重派生对象,将其地址指定给“最左端(即第一个)”base class的指针,情况和单一继承一样,因为两者都指向相同的起始地址。
2.对于第二个或后继的base class的地址指定操作,需将地址修改,加上或减去介于中间的base subobjects大小。
3.编译器通常根据派生列表中的声明次序来排列基类。
4.如图:
(四)虚拟继承:
1.Microsoft编译器:class如果有一个或多个virtual base classes,就会由器安插一个指针,指向virtual base class table。
*如下图:
2.GCC:在virtual function table中放置virtual base classes的offset。
六 对象成员的效率
七 指向Data Members的指针:
1.取一个nonstatic data member的地址,将会得到它在class中的offset。(例如:&base::a;待验证)
2.取一个绑定于真正class object身上的class member的地址,将会得到该member在内存中的地址。