首先,我想明确表示我确实理解 C++ 标准中没有 vtables 和 vptrs 的概念。但是我认为几乎所有实现都以几乎相同的方式实现虚拟调度机制(如果我错了,请纠正我,但这不是主要问题)。另外,我相信我知道虚函数是如何工作的,也就是说,我总能知道哪个函数会被调用,我只需要实现细节。
假设有人问我以下问题:
“您有带有虚函数 v1、v2、v3 的基类 B 和派生类 D:B,它覆盖了函数 v1 和 v3 并添加了一个虚函数 v4。解释虚拟调度的工作原理”。
我会这样回答:
对于每个具有虚函数的类(在本例中为 B 和 D),我们都有一个单独的指向函数的指针数组,称为 vtable。
B 的 vtable 将包含
&B::v1
&B::v2
&B::v3
D 的 vtable 将包含
&D::v1
&B::v2
&D::v3
&D::v4
现在类 B 包含一个成员指针 vptr。D 自然地继承了它,因此也包含它。在 BB 的构造函数和析构函数中设置 vptr 指向 B 的 vtable。在DD的构造函数和析构函数中设置它指向D的vtable。
任何对多态类 X 的对象 x 的虚函数 f 的调用都被解释为对 x.vptr[f 在 vtables 中的位置] 的调用
问题是:
1. 我上面的描述有什么错误吗?
2. 编译器如何知道 f 在 vtable 中的位置(请详细说明)
3. 这是否意味着如果一个类有两个基数,那么它就有两个 vptr?在这种情况下发生了什么?(尝试以与我类似的方式描述,尽可能详细地描述)
4. A 在顶部 B,C 在中间,D 在底部的菱形层次结构中发生了什么?(A 是 B 和 C 的虚拟基类)
提前致谢。