8

我正在经历这个:- https://isocpp.org/wiki/faq/multiple-inheritance#mi-delegate-to-sister

有人可以解释一下这是如何发生的以及为什么会发生这种情况吗?

4

3 回答 3

10

其他两个答案中缺少的关键是存在虚拟继承。这意味着在完整对象中只有一个 Base子对象,由Der1和共享Der2

Der1和类型中的每一个都Der2提供了该基的虚函数之一的实现,并且由于只有一个这样的对象,因此在完整对象中结合Der1Der2提供了这两个成员的实现。

当您真正调用您的类型的成员函数时,您可以分派到兄弟类Base,并且该函数在您的Base子对象中实现(通过您的兄弟类)。请注意,Der1它不调用Der2::bar,而是Base::bar将其分派给恰好位于的最终覆盖程序Der2。这与在其他情况下分派到最终覆盖器实际上没有什么不同:

struct base { virtual void f() = 0; };
struct d : base { void g() { f(); } };
struct d1 : d { void f() { std::cout << "here"; };
int main() {
   d1 x;
   x.g(); // dispatches from 'd::g' to 'd1::f' which is below in the hierarchy!
          // yeah, right, everyone knows that... no magic here
}

现在,如果继承不是虚拟的,那么Base完整类型中将有两个子对象,每个子对象都有一个(不同的)纯虚函数,您甚至无法实例化最派生类型的对象(除非提供了虚函数的定义)

于 2013-06-24T17:32:33.833 回答
1

因为这是虚函数,调用是从 VirtualFunction 表调用函数。它只是通过定义的索引在表中查找。该表在构造对象时获取数据,并且由于对象的动态类型是Join,并且该类型具有从基类继承的所有虚函数的条目。

于 2013-06-24T16:30:50.113 回答
1

简短的回答是:
虽然 Join 类是从 Der1 和 Der2 派生的,但 Base 类只有一个实例。那是因为虚拟继承。如果基类不是抽象类,并且您必须将一些参数传递给构造函数,则在 Der1 和 Der2 中都将省略这些调用,并且您必须通过 Join 传递这些参数。

于 2013-06-24T16:36:10.763 回答