class X{};
class Y:public virtual X{};
class Z:public virtual X{};
class A:public Y,public Z{};
这段代码作者给出了两种答案,与编译器有关
一是
二是我在codeblocks上运行得到的
C++中对象的大小与以下三个因素有关:
1、语言本身所造成的负担,当支持虚基类时,派生类中会一个指向虚基类子对象的指针(vtpr)或是一个相关表格(vtbl)。
2、编译器对于特殊情况所提供的优化处理。因为Y,Z都是空的,故将虚基类的1byte安插进来,第一种情况下,编译器将空的虚基类(X)安排在派生类的尾端。
3、alignment(数据对齐)的限制(CPU在处理内存数据时,并非一次提取一个memory cell,一般提取一组相邻内存单元。在32-bit machine,CPU一次从内存中读取 4个连续的memory cell(4-byte) ,这样数据运输率最高)第二点提到,有1byte被安排到尾端,故编译器自动进行alignment(对齐)。
关于第2点:c++要求每个实例在内存中都有独一无二的地址。空类也会被实例化,所以编译器会给空类隐含的添加一个字节,这样空类实例化之后就有了独一无二的地址了。所以空类的sizeof为1
故X的size为1
故第一种情况的解释如下
4bytes(指向虚基类子对象的指针)+1bytes(虚基类X安插在尾端)+3bytes(alignment)=8bytes
第二种情况:
某些情况下,编译器对第2个因素进行优化:一个空的虚基类被视为派生类对象最开头的一个部分,也就是说它并没有花费任何额外的空间。因为X之所谓被插入一个额外的字节,是因为它是空的,而Y、Z都有一个指向虚基类的指针,他们并不是空的,所以并不需要这1byte。
此时Y、Z的大小都是4bytes,自然不需要alignment,故大小为4;
class A:
■唯一共享的X的size
■Base class Y的大小-virtual base X的size=4(base class X同样)
■class A自己的大小0byte
■class A的alignment 3
所以一共是12
如果考虑第二种情况
则不需要X额外的1byte和alignment 只需要8 bytes
★一个virutal base class subobject 只会在devrived class中存在一份实体,不管它在class 继承体系中出现几次。
二、各种类的大小
class X{
int i;
char c;
};
int:4
char:1
alignment:3
class X{
int i;
char c;
virtual void f1();
virtual void f2();
};
int:4
char:1
指向vtbl的指针:4
alignment:3
子类的大小,分了下述几种情况
1、直接继承
(a)Base和Derived中都没有虚函数
class Base{
int i;
char c;
//virtual void f1();
//virtual void f2();
};
class Derived:public Base{};
(b)Base中有虚函数
class Base{
int i;
char c;
virtual void f1();
virtual void f2();
};
class Derived:public Base{};
1、虚继承
(a)Base和Derived中都没有虚函数
class Base{
int i;
char c;
virtual void f1();
virtual void f2();
};
class Derived:public virtual Base{};
可以做出如下总结:
如果base class中有虚函数
1、不管是不是virtual继承,base class和derived class都有各自的vtable(不一定只有一个)。Derived class中vtable的virtual function来自三个地方:
1-1 继承自base class的virtual function,没有经过该derived class的override
1-2 继承自base class的virtual function,被该derived class进行了override
1-3 该derived class扩充的virtual function