所以在这里我得到了一个血统解释,实际上是一个虚拟函数,为什么我们真的需要它,
但是在我的脑海中仍然存在一个问题,即编译器实际上如何解释在多重或混合继承的情况下应该使用哪个定义。例如,考虑这个例子
class Up {
public:
void func(){
...
}
};
class Middle_1 : public virtual Up {
public:
...
};
class Middle_2 : public virtual Up {
public:
...
};
class Down : public Middle_1, public Middle_2 {
public:
...
};
在上面的示例代码中,类Down
正在接收类Up
的两个定义(即一个来自Middle_1
,另一个来自Middle_2
)。但是我们确保在virtual
和Middle_1
类中使用Middle_2
标记,这将删除歧义的情况(因为编译器只需要一个定义),这就是我的问题出现的地方。
其实我有很多问题,
编译器如何选择最适合的课程?
所有情况下的选择是否相似?
这与编译器的IQ为零无关吗?
提前致谢。
答案 0 :(得分:4)
整个程序中只有一个Up
类。无需选择任何内容。
也许您想问编译器如何选择最合适的Up
子对象?表面上每个{{1}都有一个Up
子对象对象,以及每个Middle_1
子对象中的Up
子对象。编译器需要选择其中一个用于Middle_2
,对吧?
错误。使用虚拟继承,子对象不会相对于其所有者固定到位。 Down
和Middle_1
都不会创建自己的Middle_2
子对象,并且他们事先并不知道这些Up
子对象的位置。他们只知道他们会有一个。 有人必须将它们移交给Up
。
所以编译器会做一些肮脏的技巧。它将为每个Up
对象创建一个单 Up
子对象,然后告诉Down
部分和 {{1} } 和 Middle_1
部分他们的 Middle_2
子对象。因此,所有这三个部分都会将单个Down
视为自己的部分,完全忘记它实际上是共享的。
这个方案确实需要一些非平凡的IQ来发明,但是那里的每个哑编译器都能够实现。