为什么从两个空类派生的空类的大小是2?

时间:2017-06-19 07:35:38

标签: c++ class inheritance multiple-inheritance

我所知道的是,空类的大小为1只是为了符合不允许大小为0的对象(及其类)的标准。这里,我得到派生类D的大小为2。在这种情况下,为什么行为不同  假设没有从B类和C类继承的数据成员或虚拟指针到D?

#include<iostream>
using namespace std;

class A {};
class B : public A {};
class C : public A {};
class D : public B, public C {};

int main() {
    cout<<"Size of D is: "<<sizeof(D)<<endl;
    return 0;
}

2 个答案:

答案 0 :(得分:3)

对我而言,似乎是否可以在此处应用空基础优化,取决于人们如何解释[intro.object/8]

  

除非对象是位字段或基类子对象为零   size,该对象的地址是它的第一个字节的地址   占据。 两个对象 a和b,重复的生命周期不是   位字段可以具有相同的地址,如果其中一个嵌套在   其他,或者如果至少有一个是零大小的基类子对象   它们属于不同类型;否则,他们有不同的地址。

BC 是否有不同的类型?它们都是A。实际上有两个不同的A个对象。允许编译器编写者单独停在BC的分配存储,而不检查A是否为空。

值得注意的是,使用g ++,如果BC继承自单独的基础,则大小会回到1:

Live Example

#include<iostream>

class A  {};
class A1 {};
class B : public A {};
class C : public A1 {};
class D : public B, public C {};

int main() {
    std::cout << "Size of D is: " << sizeof(D) << std::endl;
    return 0;
}

答案 1 :(得分:3)

这是因为您从两个基类继承而来自同一基类A,看看当您将程序更改为此时输出如何变化

#include<iostream>
using namespace std;

class A {};
class Z {};
class B : public A {};
class C : public Z {};
class D : public B, public C {};

int main() {
    cout<<"Size of D is: "<<sizeof(D)<<endl;
    return 0;
}

如您所见,D的尺寸为1

问题类似于你可能知道的可怕钻石的问题。编译器正在尝试消除示例中A中存在的D的两个实例的歧义。并且这里没有应用空基优化,标准不需要它,编译器也没有实现它(见下文)

标准明确允许编译器不对多继承情况应用空基优化。标准here

的相关引用
  

允许标准布局类使基类强制编译器为标准布局类实现空基本优化,这可能会破坏编译器的应用程序二进制接口(ABI)。见上文9.2 / 18。这被认为不是现代编译器的关注点,除非可能存在多重继承。由于多重继承不是此提案的核心,因此如果证明有争议,将允许标准布局类或其基础使用多重继承。