52

假设我有一个带有一些成员变量但没有虚函数的基类:

class Base {
   int member;
};

和一个以非虚拟方式派生的派生类,Base没有新的成员变量,也没有虚拟函数:

class Derived : Base {
};

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

必须sizeof(Derived)等于?sizeof(Base)

4

4 回答 4

18

从 5.3.2 [expr.sizeof]

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

从 1.8 [intro.object]

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

和一个注释:

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

把这些放在一起,我认为它告诉你的是,你无法保证sizeof会告诉你什么,除了结果将大于零。事实上,它甚至似乎都不能保证sizeof(Derived) >= sizeof(Base)

于 2013-11-13T09:34:31.867 回答
13

没有这样的要求。

我能想到的语言中唯一相关的部分是,每个对象,无论是否完整,也无论是否派生最多,都有一个identity,它由它的地址和类型对给出。参照。C++11 1.8/6:

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

因此,示例的最派生对象和基本子对象都必须具有不同的身份。

Base编译器同时给出和Derived的大小当然是有意义的1,但这不是强制性的。如果Base尺寸为 1729 且Derived尺寸为 2875,则可以接受。

于 2013-11-13T09:21:05.777 回答
10

有趣的问题。我有一个示例,其中具有额外字段的派生类与基类的大小相同 (这应该是一条评论,但太大了;请接受其他答案之一,尽管如果有趣,欢迎投票。)

考虑这个简单的 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

换句话说,在派生类中增加一个额外的字段并不会使派生类变大。

关于兼容性选项 Zero-length empty base class的帮助文件主题有一些见解。

通常一个类的大小至少是一个字节,即使该类没有定义任何数据成员。设置此选项时,编译器会忽略此未使用的字节,用于内存布局和任何派生类的总大小;空基类不占用派生类中的空间。默认 = 假

看起来这个编译器的默认编译器设置的类的大小是 8 个字节,而不是 1 个字节,实际上更改这个代码示例的这个设置没有任何效果。

您可能还会发现这篇关于基类大小和上述优化的文章很有趣。它讨论了为什么类必须具有至少一个字节的大小,优化的作用,并深入研究成员函数的表示等:

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

请阅读文章以了解该引用的完整上下文。

于 2013-11-13T09:45:59.930 回答
-1
class Base {
 // int member;            I have just created an empty base class.
};

class Derived : Base {
};

现在 gcc 编译器将为 Base 和 Derived 类创建的对象提供“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 对象相同。

于 2013-11-13T10:59:28.147 回答