一:
class x{};
class y:public virtual x{};
class z:public virtual x{};
class A:public y,public z{};
1. sizeof(x)=1,虽然x为空类,但是编译器会为其分配一个字节,用来区分x所创建对象。
例如: x t1; x t2; 如果没有这个字节,就无法区分t1和t2了,加上这个字节就完美解决这个问题了。
2. sizeof(y)=4,sizeof(z)=4;因为为虚继承,所以y,z必须分配一个虚拟函数表(vptr)是四字节(32位机器)。
3. sizeof(A)=8;因为y是4字节,z是四字节,所以为8字节。
二:
nested type 声明 放在class的起始处,不然达不到你预料的结果。
三:
data member 在类对象中的内存排列顺序一般是和其声明顺序相同的。vptr一般在data member的后面。他们在一个连续区块。
四:对象和指针对data member的存取有重大差异吗?
如:X a,*b; a.data和b->data 有什么差异?
1.Static Data Member 对象和指针对Static Data Member的存取没有什么差异,因为static是存储在全局数据区,直接调用就可以。(即使是base class 的data member 也是一样)。
2.Nonstatic Data Member 的情况就比较复杂了,这就要知道它们在内存中的分配才能理解。
先说一个简单的:非虚拟继承的单继承或多重继承单链,或其data member 是在编译器对象的地址加上数据的偏移量的。
例如:a.data=0; 等价于 &a+(&X::data-1);(注:减1操作说明。指向data member 的指针,其offset总是被加上1,这样可以使编译系统区分出“一个指向data member 的指针用以指向class的第一个member”和“一个指向data member的指针没有指出任何member”两种情况)。
五:继承与data member
下面我们就来讨论情况复杂的存取情况吧(搞懂这部分瞬间觉得提升了一个level,下面的图片均来自深度探索c++模型)
1.只要继承不要多态,布局如下图:
2. 加上多态:
3.多重继承:
4.虚拟继承: