为什么 vtable 不能包含重复的函数?

Why can't a vtable contain duplicate functions?

想象一个项目,其中有一个界面 class 如下所示:

struct Interface
{
    virtual void f()=0;
    virtual void g()=0;
    virtual void h()=0;
};

假设在其他地方,有人希望创建一个 class 实现此接口,为此 fgh 都做同样的事情。

struct S : Interface
{
    virtual void f() {}
    virtual void g() {f();}
    virtual void h() {f();}
};

那么为 S 生成一个 vtable 将是一个有效的优化,其条目都是指向 S::f 的指针,从而节省了对包装函数 gh.

但是,打印 vtable 的内容表明未执行此优化:

S s;
void **vtable = *(void***)(&s);  /* I'm sorry. */
for (int i = 0; i < 3; i++)
    std::cout << vtable[i] << '\n';

0x400940
0x400950
0x400970

使用 -O3-Os 编译无效,在 clang 和 gcc 之间切换也是如此。

为什么错过了这个优化机会?

目前,这些是我考虑过(并拒绝)的猜测:

  1. vtable 打印代码实际打印垃圾。
  2. 性能提升被认为毫无价值。
  3. ABI 禁止它。

这样的优化是无效的,因为...

// somewhere-in-another-galaxy.hpp
struct X : S {
    virtual void f();
};

// somewhere-in-another-galaxy.cpp
include <iostream>
void X::f() {
    std::cout << "Hi from a galaxy far, far away! ";
}

如果编译器实现了您的优化,则此代码将无法运行。

Interface* object = new X;
object->g();

我的翻译单元的编译器不知道你的 class 内部实现,所以对于 g() 和 h() 它只是放入我的 class' 虚函数 table引用您 class' VFT 中的相应条目。