如果没有新的成员variables与基类相比,C ++是否允许增加派生类的大小?

假设我有一个基类,有一些成员variables,没有虚函数:

class Base { int member; }; 

以及一个派生类,它以非虚方式从Base派生,并且没有新的成员variables,也没有虚函数:

 class Derived : Base { }; 

显然, sizeof(Derived)不能小于sizeof(Base)

sizeof(Derived)需要等于sizeof(Base)

从5.3.2 [expr.sizeof]

当应用于类时,[ sizeof ]的结果是该类的对象中的字节数,包括将该types的对象放置在数组中所需的任何填充。 大多数派生类的大小应大于零(1.8)。

从1.8 [intro.object]

除非是位域(9.6),否则大多数派生对象的大小应该是非零的,并占用一个或多个字节的存储空间。 基类子对象可能具有零大小。 PODtypes(3.9)的一个对象应占用连续的存储字节。

和一张纸条:

基类子对象的实际大小可能小于将sizeof应用于子对象的结果,这是由于虚拟基类和对基类子对象的不太严格的填充要求。

把它们放在一起,我想它告诉你的是,你无法确定什么样的sizeof可以告诉你,除了结果会大于零。 实际上,它甚至不能保证sizeof(Derived) >= sizeof(Base)

没有这样的要求。

我能想到的语言的唯一相关部分是, 每一个对象,无论是否完整,以及是否派生最多,都有一个由它的地址和types组成的对象的身份 。 参看 C ++ 11 1.8 / 6:

如果一个对象是另一个对象的子对象,或者如果至less有一个是大小为零的基类子对象,并且它们是不同types的,则两个不是位域的对象可以具有相同的地址; 否则应有明确的地址。

因此,示例中派生最多的对象和基本子对象都必须具有不同的标识。

对于编译器来说, BaseDerived的大小都是1 ,这肯定是有意义的,但这不是强制性的。 如果Base规模是1729, Derived规模是2875,这是可以接受的。

有趣的问题。 我有一个例子,其中带有额外字段的派生类与空的基类具有相同的大小 (这应该是一个评论,但太大了,请接受其他答案之一,虽然upvotes是值得欢迎的,如果它是有趣的。)

考虑这个微不足道的C ++程序:

 class A {}; class B : public A { int m_iInteger; }; int _tmain(int argc, _TCHAR* argv[]) { printf("A: %d\r\n", sizeof(A)); printf("B: %d\r\n", sizeof(B)); printf("int: %d\r\n", sizeof(int)); return 0; } 

如果sizeof(int)是4,你会期望输出是什么? 也许是这样的:

 A: 0 B: 4 int: 4 

我的编译器 – Embarcadero C ++ Builder 2010 – 提供了输出:

 A: 8 B: 8 int: 4 

换句话说, 在派生类中添加额外的字段不会使派生类更大。

对兼容性选项零长度空基类的帮助文件主题有一些洞察。

通常,类的大小至less是一个字节,即使类没有定义任何数据成员。 当你设置这个选项时,编译器会忽略内存布局的这个未使用的字节和任何派生类的总大小。 空的基类不会消耗派生类中的空间。 默认= False

看来这个编译器的默认编译器设置的类的大小是8个字节,而不是一个,实际上改变这个代码示例的设置没有影响。

你也可以在基类的大小和上面的优化中find这篇文章 。 它讨论了为什么类必须至less有一个字节的大小,优化是什么,并深入到成员函数的表示等:

事实上,这个标准要求一个物体的大小不能为零, 它还要求在派生类中,基类的数据成员应该出现在用户声明的派生类的数据成员之前。 但是, 基类子对象不被视为完整的对象。 因此,可以在不违反规则的情况下从派生对象中移除基类子对象。 换句话说,在对象t中,S和x的偏移量可能会重叠。

请阅读该报价全文的文章。

 class Base { // int member; I have just created an empty base class. }; class Derived : Base { }; 

现在,gcc编译器会为Base和Derived类创build的对象赋予“size> 0”。 gcc编译器只是向用户提供对象的地址。

  Note:Derived class would contain base class members, so obviously we can think of sizeof(derived class) greater then sizeof(base class). But this depends on the compiler if it allocates some extra space while defining the derived class. 

我现在的gcc编译器显示Base和Derived的sizeof对象是相同的。