钻石继承和纯虚函数 [英] Diamond inheritance and pure virtual functions
问题描述
A ---> B ---> D
\ ---> C ------ ^
...注意,Herb Sutter写道关于多重继承的3篇优秀文章(1)here ,(2)here and (3)在这里。他在本周的这里写了一大堆有用的文章。强烈建议...
首先,我不确定我是否正确地获得了您的层次结构。我认为它是这样的:
struct A {
virtual void F()= 0;
};
struct B:{void F(){}};
struct C:A {};
struct D:B,C {};
嗯,D是抽象的,因为有两个 A
D类型的对象中的子对象:通过B的格子由 B
具体化的子对象,以及通过<$ ç$ C> C 。我认为你有一个指向 D
的指针并尝试调用 F
。是的,会产生歧义,因为编译器会在两个单独的格子中找到两个函数 F
:
D - > B :: F
D - > C - > A :: F
看起来像这样:
F()F()
AA
| |
F()BC
\ /
D
您可以通过从A中派生出来正式地修复这种情况:
struct B:virtual A {void F(){}};
struct C:virtual A {};
struct D:B,C {};
然后你有这种情况,称为钻石继承:
F()
A
/ \
F()BC
\ /
D
通过查找,发现有 B :: F
覆盖 A :: F
。虽然 A :: F
仍然可以通过 D :: C :: A
到达,但这不再是歧义,因为 A
是继承的虚拟。
这是否是您的特定问题的正确解决方案 - 当然不确定。通常有更好的方法比从课堂中派生虚拟。关于虚拟函数表合并的问题 - 完全取决于实现。据我所知, GCC
将保留一个指向 D
的虚拟表中的一个实例的指针,如果我们得到虚拟。
Imagine a standard diamond inheritance. Class A defines pure virtual function fx, class B defines implementation for fx, classes C and D do nothing with fx. When trying to call fx on instance of class D you'll get 'ambiguous function call' error although there is only one implementation of fx. This can be solved by B and C inheriting from A in virtual manner. Is it a correct solution for the problem? How exactly does virtual inheritance handle merging of virtual function tables?
A--->B--->D
\--->C------^
... Note, Herb Sutter wrote 3 excellent articles about multiple inheritance (1) here, (2) here and (3) here . He wrote a whole other bunch of useful articles in guru-of-the-week here. Highly recommended ...
First, i'm not sure that i get your hierarchy right. I take it it is like this:
struct A {
virtual void F() = 0;
};
struct B : A { void F() { } };
struct C : A { };
struct D : B, C { };
Well, D is abstract, because there are two A
subobjects in an object of type D: One that is made concrete by B
through the lattice of B, and one that is still abstract in the lattice going through C
. I take it you have a pointer to D
and try to call F
. Yes, an ambiguity arises, because the compiler finds two functions F
in two separate lattices:
D -> B::F
D -> C -> A::F
Looking like this:
F() F()
A A
| |
F() B C
\ /
D
You can fix that situation formally by deriving from A virtually:
struct B : virtual A { void F() { } };
struct C : virtual A { };
struct D : B, C { };
You then have this situation, called diamond inheritance:
F()
A
/ \
F() B C
\ /
D
And doing the lookup, it finds that there is B::F
overriding A::F
. Although A::F
can still be reached through D::C::A
, that is not an ambiguity anymore, because A
was inherited virtual.
Whether this is the correct solution in your particular problem - that's of course not certain. There are most often better ways than deriving virtual from a class. To your question about merging of virtual function tables - that's completely depending on the implementation. GCC
, as far as i know, will keep a pointer to the one A instance in the virtual table of D
, if we derive virtual.
这篇关于钻石继承和纯虚函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!