空类的大小

1、为何空类的大小不是0呢?

为了确保两个不同对象的地址不同,必须如此。

类的实例化是在内存中分配一块地址,每个实例在内存中都有独一无二的二地址。同样,空类也会实例化,所以编译器会给空类隐含的添加一个字节,这样空类实例化后就有独一无二的地址了。所以,空类的sizeof为1,而不是0.

2、请看下面的类:

class A{ virtual void f(){} };

class B:public A{}

此时,类A和类B都不是空类,其sizeof都是4,因为它们都具有虚函数表的地址。

3、请看:

class A{};

class B:public virtual A{};

此时,A是空类,其大小为1;B不是空类,其大小为4.因为含有指向虚基类的指针。

4、多重继承的空类的大小也是1.

class Father1{}; class Father2{};

class Child:Father1, Father2{};

它们的sizeof都是1.

5、何时共享虚函数地址表:

如果派生类继承的第一个是基类,且该基类定义了虚函数地址表,则派生类就共享该表首址占用的存储单元。对于除前述情形以外的其他任何情形,派生类在处理完所有基类或虚基类后,根据派生类是否建立了虚函数地址表,确定是否为该表首址分配存储单元。


6、扩展

首先,先看下面几个类:

class X{};

class Y : public virtual X {};

class Z : public virtual X {};

class A : public virtual Y {};

class B : public Y, public Z{};

class C : public virtual Y, public virtual Z {};

class D : public virtual C{};

在VC6.0上执行的结果为为:

sizeof(X):1

sizeof(Y):4

sizeof(Z):4

sizeof(A):8

sizeof(B):8

sizeof(C):12

sizeof(D):16

首先,对于class X,其实它并不是空的,它隐含着被编译器添加了一个char,那么为什么要添加这个char,我们来看,有这样的定义X x,则x肯定是又地址的,那既然x有地址,OK,sizeof(x)肯定就不为0了撒。

对于class Y和class Z,都有额外的负担,那么这个负担反映在指向virtual base class subobject上的指针。那照这样说,sizeof(Y)就应该等于5(先不考虑字节对齐)了?其实有些编译器提供了一些特殊处理,这使得一个empty virtual base class被视为derived class object最开头的一部分,也就是说它并没有花费任何空间,即这个1bytes被省了。

同样,对于class A,本身base class Y的大小为4,加个指针,则为8了。

对于class B,也很简单,class Y和class Z的大小都为4。

现在来看class C,因为他虚继承了Y和Z,所以它应该添加2个指针,在加上Y和Z,不应该是16么,那为什么结果是12呢?我们可以看到,Y和Z都是虚派生自class X,而一个virtual base class subobject只会在derived class中存在一份实体,不管它在class继承体系中出现了多少次。

如果说我把之前的类重新改下,新添加一个“class X1 {}; ”,而把class Z改成“class Z : public virtual X1 {}; ”,那么这个时候sizeof(C)就等于16了。

最后对于class D来说,应该很简单了


你可能感兴趣的:(IT面试)