1. 继承关系
通过菱形继承关系讨论在继承体系中不同继承的情况,Base类和Derive类的尺寸。
class Base{};
class SubBase1 : public Base {};
class SubBase2 : public Base {};
class Derive : public SubBase1, public SubBase2{};
类之间的关系,用图表示如下:
2. 普通public继承
在普通public继承的体系下,上述继承关系如下:
在这种继承体系下,所有的Derived类都以public的形式继承自Base类。通过程序得到不同平台下的大小:Windows platform
继承体系下所有的Empty类都占 1 byte。
在Windows平台下,所有Empty(空)类的大小都为1。对于编译器来说,为了给类的不同对象分配唯一一个存储空间,会为空类安插一个char即 1 byte。GNU-GCC Platform
使用gcc编译器编译测试的类的size结果:
在继承体系下,Empty类占 1 byte;单继承的Empty类占 1 byte;多继承的Empty类占 2 byte。
Class Size:
Base Class: 1
SubBase1 Class: 1
SubBase2 Class: 1
Derive Class: 2
a. Base类的大小为1,因为Base类是一个Empty类,编译器自动为其安插1个char即 1 byte;
b. SubBase1类的大小为1, 因为SubBase1类继承自Base类(一个Empty类),由于Base类有1 byte的空间,所以在SubBase1中有1 byte存放Base子类。又由于SubBase1是Empty类占 0 byte。综上所属,SubBase1占 1 byte。
c. 同理,SubBase2也占用 1 byte;
d. Derive类的大小为 2 byte。SubBase1和SubBase2分别占 1 byte。由于Derive类是Empty类占 0 byte。综上所述,空的Derive类的大小是 2 byte, 结构如下所示:
3. 虚继承
在虚继承体系中,SubBase1和SubBase2以virtual继承的方式继承自Base类,其继承结构如下:
在虚继承的体系下,无论Windows平台还是GNU-Gcc的编译环境下,结果相同:
在 64 bit的platform下,Empty类占 1 byte;单继承的Empty类占 8 byte; 多继承的Empty类占 16 byte。Base类的大小为 1 byte。编译器为了给空类的对象分配一块唯一的内存空间,为Empty类安插 1 byte的占位符;
SubBase1类的大小为 8 byte。当一个类 A 虚继承自另外一个类 B 时,在类A中会有一个指向类B的子对象的指针。由于SubBase1虚继承自Base,所以SubBase1中有一个指向Base类的指针占 8 byte (64bit OS下)。又因为虚基类Base类是一个Empty类,编译器会为Base安插 1 byte的占位符,但是在编译器优化的情况下,由于Base类在SubBase1类的最开始的位置,不占任何额外的空间,因此,编译器就不再为Base分配占位符。综上所述,SubBase1占 8 byte,结构如下:SubBase2类的大小为 8 byte。同理,SubBase1占 8 byte;
Derive类的大小为 16 byte。Derive类结构中包含以下部分:
a. Base类由编译器分配的 1 byte;
b. SubBase1类的 8 bytes 和SubBase2类的 8 bytes, 共占 16 byte;
c. Derive类是Empty类占 0 byte;
综上所述,当前情况下Derive类占 17 byte, 由于alinment(字节序对齐)的作用,编译器会为Derive类添加 7 bytes( 对于64 bit操作系统,8 byte对齐 )来满足字节对齐。由于编译器优化的作用,Base类是Derive类的一部分不占额外的空间,因此,编译器不为Base类分配 1 byte的占位符。此时,Derive类占 16 bytes,结构如下: