class X{}; class Y :public virtual X{}; class Z :public virtual X{}; class A :public Y, public Z{}; void main() { cout << sizeof(X) << " " << sizeof(Y) << " " << sizeof(Z) << " " << sizeof(A); system("pause"); }
vs2013的结果是1,4,4,8
因为Y,Z继承自X,会有指针指向父类。
X内部的1byte,使得这个class的多个object得以在内存中配置独一无二的地址。
一、data member的布局
nonstatic data members在class object中的排列顺序将和其被声
明的顺序一样,任何中间介入的static data member都不会被放进对象布局中。
C++standard要求,在同一个access section中,member的排列只需符合较晚出现的member在class object中有较高的地址即可,各个member并不一定得连续排列。
编译器可能会合成一些内部使用的data member,以支持整个对象模型,vptr就是这样的东西,当前所有的编译器都把它安插在每一个内含virtual function之class的object内,vptr的安放位置依不同的编译器决定。
二、data member的存取
1.static data member
每一个static data member只有一个实体,存放在程序的data segment之中,并不再class object中,每次程序取用static member,就会被内部转化为对该唯一的extern实体的直接操作,也就是说通过一个指针和通过一个对象来存取static data me
mber完全相同。
2.nonstatic data member
Point3D origin,*pt=&origin; origin.x=0; pt->x=0;
当Point3D是一个derived class,而在其继承结构中有一个virtual base class,并且被存取的member是一个从该virtual base class继承而来的member时,上述两种方式有重大差异。这时候我们不知道pt指向哪一个class(多态),所以这个存取操作必须延迟到程序运行时。但使用origin,member的offset位置在编译期间就固定了。
欲对一个nonstatic data member进行存取操作,编译器需要把class object的起始地址加上data member的偏移量(offset)。
【深度探索C++对象模型】data语义学