想象一下标准的菱形继承(钻石问题)。 A 类定义纯虚函数 fx,B 类定义 fx 的实现,C 类和 D 类对 fx 不做任何处理。当尝试在类 D 的实例上调用 fx 时,尽管只有一个 fx 实现,但您会收到“模糊函数调用”错误。这可以通过B和C以虚拟的方式继承A来解决。它是问题的正确解决方案吗?虚继承究竟是如何处理虚函数表合并的?
A--->B--->D
\--->C------^
最佳答案
... 注意,Herb Sutter 写了 3 篇关于多重继承的优秀文章 (1) here , (2) here和 (3) here .他在本周大师中写了一大堆有用的文章 here .强烈推荐...
首先,我不确定我是否正确理解了您的层次结构。我认为它是这样的:
struct A {
virtual void F() = 0;
};
struct B : A { void F() { } };
struct C : A { };
struct D : B, C { };
嗯,D 是抽象的,因为在类型 D 的对象中有两个 A
子对象:一个是 B
通过 B 的格具体化的,和一个在通过 C
的格子中仍然是抽象的。我认为您有一个指向 D
的指针并尝试调用 F
。是的,出现了歧义,因为编译器在两个单独的格中找到了两个函数 F
:
D -> B::F
D -> C -> A::F
看起来像这样:
F() F()
A A
| |
F() B C
\ /
D
您可以通过从 A 虚拟派生来正式解决这种情况:
struct B : virtual A { void F() { } };
struct C : virtual A { };
struct D : B, C { };
然后你有这种情况,称为菱形继承:
F()
A
/ \
F() B C
\ /
D
在进行查找时,它发现 B::F
覆盖了 A::F
。虽然 A::F
仍然可以通过 D::C::A
到达,但这不再是歧义了,因为 A
是继承的虚拟的。
这是否是您的特定问题的正确解决方案 - 当然不能确定。通常有比从类派生 virtual 更好的方法。关于合并虚函数表的问题——这完全取决于实现。 GCC
,据我所知,如果我们派生 virtual,将在 D
的虚拟表中保留一个指向 A 实例的指针。
关于c++ - 菱形继承(钻石问题)和纯虚函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/457609/