0

我读到抽象类仍然可以有一个表。但我对它的 vtable 中有多少条目感到困惑。例如,如果我的抽象类是:

class Circle(){
    virtual void draw() = 0;
}

那么它的 vtable 中有多少条目?另外,我是否正确地说这个抽象类在其 vtable 中有 1 个条目?谢谢你的帮助。

class Circle(){
    virtual double a{ return 0.0; }
    virtual void draw() = 0;
}
4

3 回答 3

6

每个虚函数都可以被覆盖。编译器必须建立某种机制来动态地分派对每个虚函数的调用,以便代码调用正确的覆盖版本,这取决于对象的实际类型。该机制通常是一个 vtable,并且每个虚拟功能都必须有一个条目。所以第一个例子有一个条目,第二个例子有两个。请注意,将函数标记为纯虚函数不会影响这一点;它仍然必须动态调度。

于 2018-03-15T14:50:06.460 回答
4

首先,vtables 是一个实现细节。只要你不做非常奇怪的事情,你就应该忽略它们的存在。

其次,尽管所有编译器都使用 vtables 来实现虚拟调度,但它们的实现方式存在差异。对于某些人来说,一个 vtable 条目只是一个函数指针;对于其他人来说,它是一个指针和一个偏移量。有些编译器有一个虚拟析构函数的入口,有些编译器有两个,甚至更多。有些为协变覆盖的函数添加了一个新条目,而另一些则可能没有。

最重要的是,一般来说,您不应该担心这个问题。如果您对实现细节感兴趣,例如可以阅读Itanium C++ ABI,这是 Linux 编译器通常遵循的。

于 2018-03-15T14:57:47.143 回答
2

好吧,vtables 是一个实现细节,尽管它无处不在。

由于Circlector-body 和 dtor-body 都没有调用它的任何函数,尤其是没有调用虚拟函数,并且由于纯虚函数而它是抽象的Circle,因此即使实际上甚至创建了 的 vtable,它也永远不会被使用。

无论如何,理论上的 vtable 至少需要一个条目来std::type_info支持 和任何其他支持dynamic_cast,每个虚函数需要一个,如果 dtor 是虚拟的,则需要两个(一个仅用于 dtor,一个用于 dtor + 释放delete)。

对于您的第二个示例,至少有 3 个条目(2 个虚拟功能 + RTTI)。

于 2018-03-15T14:59:12.717 回答