我正在经历这个:- https://isocpp.org/wiki/faq/multiple-inheritance#mi-delegate-to-sister
有人可以解释一下这是如何发生的以及为什么会发生这种情况吗?
我正在经历这个:- https://isocpp.org/wiki/faq/multiple-inheritance#mi-delegate-to-sister
有人可以解释一下这是如何发生的以及为什么会发生这种情况吗?
其他两个答案中缺少的关键是存在虚拟继承。这意味着在完整对象中只有一个 Base
子对象,由Der1
和共享Der2
。
Der1
和类型中的每一个都Der2
提供了该基的虚函数之一的实现,并且由于只有一个这样的对象,因此在完整对象中结合Der1
并Der2
提供了这两个成员的实现。
当您真正调用您的类型的成员函数时,您可以分派到兄弟类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
完整类型中将有两个子对象,每个子对象都有一个(不同的)纯虚函数,您甚至无法实例化最派生类型的对象(除非提供了虚函数的定义)
因为这是虚函数,调用是从 VirtualFunction 表调用函数。它只是通过定义的索引在表中查找。该表在构造对象时获取数据,并且由于对象的动态类型是Join,并且该类型具有从基类继承的所有虚函数的条目。
简短的回答是:
虽然 Join 类是从 Der1 和 Der2 派生的,但 Base 类只有一个实例。那是因为虚拟继承。如果基类不是抽象类,并且您必须将一些参数传递给构造函数,则在 Der1 和 Der2 中都将省略这些调用,并且您必须通过 Join 传递这些参数。