为什么不使用只有一个虚拟继承的钻石继承呢
Why not diamond inheritance with only one virtual inheritance?
假设我们有经典的多重继承模式:
class Base {
int baseMember;
};
class A : public Base {
int aMember;
};
class B : public Base {
int bMember;
};
class Derived : public A, public B {
int derivedMember;
};
这将在内存中布局派生对象,如下所示:
- 基本字段<--(基础*)(A*)这个
- A的字段
- 基本字段<--(基数*)(B*)这个
- B的字段
- 派生的字段
为了防止Base的字段重复,默认方法是从A和B:虚拟继承Base
class A : public virtual Base {
...
class B : public virtual Base {
这将导致以下布局:
- 到基字段的偏移量<--(A*)这个|这个
- A的字段
- 到基字段的偏移量<--(B*)这个
- B的字段
- 派生的字段
- 基本字段<--(基数*)这个|(基数*
这解决了这个问题,同时还需要应用偏移量来从其他类访问Base的字段(和虚拟函数)。
但为什么以下不可能呢?
- 基本字段<--(基数*)(B*)这个|(基数*
- A的字段
- 到基字段的偏移量<--(B*)这个
- B的字段
- 派生的字段
这将允许A和Derived在没有开销的情况下访问Base,没有重复,甚至可以将大小缩小1个整数。但是,如果我尝试,编译器仍然会复制Base的字段(将它们放在B的字段后面)。
注意:我知道有人问过类似的问题,但我没有看到为什么这不可能。
编辑:4年后回过头来看,这可能与Derived中的"对Base字段的偏移"必须为负有关。
在看到Derived之前,您需要先布局A和B。一旦你选择了布局,它就会被固定在石头上。派生类和所有其他类必须将其用于其A和B子对象。(每个完整类的虚拟基准位置可能不同,不被视为布局的一部分)。
现在,在虚拟继承的情况下,A是如何布局的?它必须包含基本字段的偏移量,因为我们不知道A将如何在程序的其他部分中使用。它可能是一些尚未编写的派生类的第一个基类,也可能是第七个基类。但是,使用A的函数现在必须有一种方法将A转换为Base,而无需等待这些派生类的定义。
B.当然也是如此
因此,A和B都有自己的偏移集到Base字段。Derived不能做出其他决定,因为它可能不是唯一继承a或B的类。
相关文章:
- 钻石继承虚拟成员铸造与指针
- 接口的钻石继承(C++)
- 在钻石问题的求解中,为什么要虚拟地继承两次grand-parent类
- c++ 中的函数重载如何在没有钻石继承的情况下工作?
- 多个虚拟(钻石)继承
- C++解决没有虚拟继承的钻石继承问题
- 多种继承C 的钻石问题
- 如何调用所有基本类的复制构造函数,以在C 中复制钻石继承中最派生的类对象
- 假设钻石继承打破了C++的封装是否正确?
- C++多个钻石继承和纯虚函数
- 虚拟继承如何解决 c++ 中的多重继承(钻石)?它将走哪条路
- 首选钻石继承中一个类的变量
- 钻石继承,C++ 处理
- 复杂的钻石问题:C++虚拟继承
- 将 Boost.Serialization 直接与虚拟钻石继承一起工作
- qt qsharedDatapointer多重继承钻石图案
- C 钻石接口继承
- 钻石继承最低基类构造函数
- 钻石继承方案在 G++ 中编译良好,但在 VC++/Eclipse 中产生警告/错误
- 多重继承钻石