我知道钻石问题,但问题是 - 当我谷歌"虚拟继承"结果提到仅钻石问题。我想知道它是如何工作的,它与正常继承有什么不同。
我知道当一个类(通常)继承自另一个类时,它只包含其所有成员(字段和方法,不考虑访问级别)。其中一些可能会被新成员覆盖或隐藏,但他们仍然存在。继承还定义了层次结构中类之间的某些关系,这些关系会影响转换和多态性。
现在虚拟继承有何不同?例如:
class A
{
public:
int a;
int b;
void fun(int x)
{}
void gun(int x)
{}
};
class B : public A
{
public:
int a;
int c;
void fun(int x)
{}
void hun(int x)
{}
};
class C : virtual public A
{
public:
int a;
int c;
void fun(int x)
{}
void hun(int x)
{}
};
B
和C
之间有什么区别?我的例子没有任何其他差异吗?标准说什么?另外,如果C ++ 03和C ++ 11之间存在差异,请提及它。
答案 0 :(得分:5)
使用单一级别的继承,行为没有区别。
不同之处在于从多个基类继承时,它们本身具有公共基类:
struct A {};
struct B : virtual A {};
struct C : virtual A {};
struct D : B,C {};
在此示例中,使用虚拟继承,D
只包含一个A
子对象,其B
和C
个子对象共享;这是“钻石”模式:
A
/ \
B C
\ /
D
如果没有虚拟继承,它将包含两个A
子对象,而不包含“菱形”:
A A
| |
B C
\ /
D
有或没有多重继承,如果你有多个继承级别仍然存在差异:虚拟基类必须由派生程度最高的类初始化,而不是由其直接派生类初始化。这是为了避免在多重继承的情况下出现歧义,其中(在上面的示例中)B
和C
都将负责初始化共享A
。