虚拟继承如何解决“钻石"问题?(多重继承)歧义?
class A { public: void eat(){ cout<<"A";} };
class B: virtual public A { public: void eat(){ cout<<"B";} };
class C: virtual public A { public: void eat(){ cout<<"C";} };
class D: public B,C { public: void eat(){ cout<<"D";} };
int main(){
A *a = new D();
a->eat();
}
我理解钻石问题,上面的代码没有这个问题.
I understand the diamond problem, and above piece of code does not have that problem.
虚拟继承究竟是如何解决问题的?
How exactly does virtual inheritance solve the problem?
我的理解:当我说 A *a = new D();
时,编译器想知道是否可以将 D
类型的对象分配给 A 类型的指针
,但它有两条路径可以走,但不能自己决定.
What I understand:
When I say A *a = new D();
, the compiler wants to know if an object of type D
can be assigned to a pointer of type A
, but it has two paths that it can follow, but cannot decide by itself.
那么,虚拟继承是如何解决这个问题的(帮助编译器做出决定)?
So, how does virtual inheritance resolve the issue (help compiler take the decision)?
推荐答案
您想要:(可通过虚拟继承实现)
You want: (Achievable with virtual inheritance)
A
/
B C
/
D
而不是:(没有虚拟继承会发生什么)
And not: (What happens without virtual inheritance)
A A
| |
B C
/
D
虚拟继承意味着只有 1 个 A
基类的实例,而不是 2 个.
Virtual inheritance means that there will be only 1 instance of the base A
class not 2.
您的类型 D
将有 2 个 vtable 指针(您可以在第一个图中看到它们),一个用于 B
,一个用于 C
他们实际上继承了A
.D
的对象大小增加了,因为它现在存储了 2 个指针;但是现在只有一个A
.
Your type D
would have 2 vtable pointers (you can see them in the first diagram), one for B
and one for C
who virtually inherit A
. D
's object size is increased because it stores 2 pointers now; however there is only one A
now.
所以 B::A
和 C::A
是相同的,所以不会有来自 D
的歧义调用.如果你不使用虚拟继承,你有上面的第二个图.任何对 A 成员的调用都会变得模棱两可,您需要指定要采用的路径.
So B::A
and C::A
are the same and so there can be no ambiguous calls from D
. If you don't use virtual inheritance you have the second diagram above. And any call to a member of A then becomes ambiguous and you need to specify which path you want to take.
维基百科有另一个很好的纲要和例子
相关文章