假设我们有经典的多继承模式:
class Base {
int baseMember;
};
class A : public Base {
int aMember;
};
class B : public Base {
int member;
};
class Derived : public A, public B {
int derivedMember;
};
这将在内存中列出Derived对象:
为了防止Base的字段被复制,默认方法是从A和B虚拟地继承Base:
class A : public virtual Base {
...
class B : public virtual Base {
这将导致以下布局:
这解决了这个问题,需要权衡你必须应用偏移来从其他类访问Base的字段(和虚函数)。
但为什么以下情况不可能?
这将允许A和Derived在没有开销的情况下访问Base,没有重复,甚至将大小缩小1整数。但是,如果我尝试它,编译器仍然会复制Base的字段(将它们放在B的字段后面)。
note :我知道有类似的问题,但我没有看到为什么这是不可能的。
答案 0 :(得分:2)
在看到Derived之前,你需要布置A和B.一旦你选择了布局,它就是一成不变的。派生和所有其他类必须将它用于A和B子对象。 (虚拟基本位置可能因每个完整的类而异,并且不被视为布局的一部分。)
现在,在虚拟继承的情况下如何布置A?它必须包含offset-to-Base字段,因为我们不知道A将如何在程序的其他部分中使用。它可能是某些尚未编写的派生类的第一个基类,或者是第七个。但是使用A的函数现在必须有一种方法将A转换为Base,而无需等待定义这些派生类。
关于B.
当然也是如此所以A和B都是自己的offsset-to-Base字段。 Derived无法做出其他决定,因为它可能不是继承A或B的唯一类。