15

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

4

3 回答 3

8

是的,他们有。这有很多很好的理由。

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

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

可能还有其他我没有想到的原因。

希望能帮助到你。

于 2012-06-25T20:01:17.787 回答
5

从纯粹的 C++ 角度来看,这是一个学术问题。虚拟功能不必用 vtables 实现,如果它们没有可移植的方式来获取它们。

如果您特别关心 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;
}

)

于 2012-06-25T19:55:16.840 回答
1

vtable 不是必需的,但很少优化出来。MSVC 提供了__declspec(novtable)扩展,它明确地告诉编译器可以删除 vtable。如果没有,编译器将不得不检查自己是否未使用 vtable。这不是特别难,但仍然远非微不足道。而且由于它在常规代码中没有提供真正的速度优势,因此我知道的任何编译器都没有实现检查。

于 2012-06-26T08:20:32.000 回答