我最近一直在学习一些关于虚拟表的更“深入”的东西,我想到了这个问题。
假设我们有这个样本:
class A {
virtual void foo();
}
class B : public A {
void foo();
}
在这种情况下,据我所知,每个类都会存在一个 vtable,并且调度将非常简单。
现在假设我们将 B 类更改为如下所示:
class B : public C, public A {
void foo();
}
如果类 C 有一些虚方法,则 B 的分派机制会更复杂。对于两个继承路径 BC、BA 等,可能会有 2 个 vtable。
从我到目前为止所学到的东西看来,如果代码库函数中还有其他地方是这样的:
void bar(A * a) {
a->foo();
}
它现在需要使用更复杂的调度机制进行编译,因为在编译时我们不知道“a”是指向 A 还是 B。
现在的问题。假设我们将新的 B 类添加到我们的代码库中。在我看来,它似乎不太可能需要在使用指向 A 的指针的任何地方重新编译代码。
据我所知,vtables 是由编译器创建的。但是,链接器可能在重定位期间解决了此修复问题吗?在我看来,我确实找不到任何证据可以确定,因此现在就去睡觉:)