界面vtable

Seb*_*ann 14 c++ polymorphism interface vtable

接口(仅具有纯虚函数的多态类)是否具有vtable?由于接口本身不实现多态函数并且不能直接构造,因此链接器不需要放置vtable.是这样吗?我特别关注MSVC编译器.

小智 8

是的,他们这样做.并且有很多充分的理由.

第一个很好的理由是即使是纯虚方法也有实现.隐式或显式.调用纯虚函数的技巧相对容易,所以你基本上可以为你的一个提供一个定义,调用它,看看会发生什么.出于这个原因,首先应该有一个虚拟表.

将虚拟表放入基类有另一个原因,即使它的所有方法都是纯虚拟的,但是没有其他数据成员.使用多态时,会在程序周围传递指向基类的指针.为了调用虚方法,编译器/运行时应该计算出虚拟表与基指针的相对偏移量.如果C++没有多重继承,那么可以假定从抽象基类零偏移(例如),在这种情况下,那里可能没有vtable(但由于理由#1,我们仍然需要它).但由于涉及多重继承,因此根据基类的数量(和类型)可能存在两个或三个vtable,但是技巧ala"vtable存在0偏移"将不起作用.

我可能还有其他原因.

希望能帮助到你.

  • 我不相信你的第一个理由.我很确定调用纯虚函数的唯一方法是(a)非虚拟地调用它,不使用vtable,或者(b)通过从部分的构造函数/析构函数中调用它来调用未定义的行为构造对象,根本不需要调用它.或者你知道另一个我没有的技巧吗? (3认同)
  • 你引用的技巧是,它既不需要定义纯虚函数(在_odr_规则下),也不会导致未定义的行为因为我不知道任何这样的技巧? (2认同)

CB *_*ley 5

从纯粹的C++角度来看,这是一个学术问题.虚拟函数不必用vtable实现,如果它们没有可移植的方法来实现它们.

如果您特别关注MSVC编译器,则可能需要使用它来修饰接口__declspec(novtable).

(通常,在通常的实现中,抽象类可能需要vtable,例如:

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

void h(Base& b) {
    b.f(); // Call f on a Base that is not (yet) a Derived
           // vtable for Base required
}

Base::Base() {
    h(*this);
}

struct Derived : Base {
    void g() {}
};

int main() {
    Derived d;
}
Run Code Online (Sandbox Code Playgroud)

)