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

PBS*_*PBS 6 c++ vtable compiler-optimization

想象一个项目,其中有一个如下所示的接口类:

struct Interface
{
    virtual void f()=0;
    virtual void g()=0;
    virtual void h()=0;
};
Run Code Online (Sandbox Code Playgroud)

假设其他地方,有人希望创建一个类实现这个接口,为此f,g,h都做同样的事情.

struct S : Interface
{
    virtual void f() {}
    virtual void g() {f();}
    virtual void h() {f();}
};
Run Code Online (Sandbox Code Playgroud)

然后,它会生成一个虚函数表的有效优化S其条目都指向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';
Run Code Online (Sandbox Code Playgroud)

0x400940
0x400950
0x400970

与clang和gcc之间的切换一样编译-O3-Os没有效果.

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

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

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

Ala*_*ton 2

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

// 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! ";
}
Run Code Online (Sandbox Code Playgroud)

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

Interface* object = new X;
object->g();
Run Code Online (Sandbox Code Playgroud)

我的翻译单元的编译器不知道您的类内部实现,因此对于 g() 和 h(),它只是将我的类的虚拟函数表引用放入您的类的 VFT 中的相应条目。