【问题标题】:If there are virtual methods, is vtable is going to be created?如果有虚方法,会创建 vtable 吗?
【发布时间】:2011-08-03 02:01:18
【问题描述】:

如果我像这样创建一个非常简单的类:

class A
{
  public :
    virtual void foo()
    {
    }
};

(无虚拟析构函数)编译器会创建 vtable 吗? 或者现代编译器是否足够聪明,可以识别这种情况(这可能是错误的复制和粘贴)并且不会为此类类添加虚拟表?

【问题讨论】:

  • 一种常见的技术是使用第一个虚拟非内联成员发出 vtable。我不知道在这种情况下存在虚拟非内联成员的后备方案是什么,但这并不是比内联函数或模板实例化中的静态更糟糕的问题。
  • 如果碰巧没有其他虚函数,虚析构函数只是强制类为多态的一种方式。 (如果您打算通过指向 A 的指针删除派生类,这也是必需的)。
  • @AProgrammer - 编译器可能必须生成大量 vtable 副本,并让链接器对其进行排序。

标签: c++ vtable


【解决方案1】:

v-table 是一个实现细节。将 v-tables 用于虚函数的编译器将为此类创建一个。那些不会,不会。

【讨论】:

  • 有哪些替代方案?
  • @Jason:见this questionthis one
  • 你说得对,它是一个实现细节,但有没有现代编译器不这样做?
  • @VJo:我将向您介绍我为 Jason 链接的两个问题。它们现在出现在您问题右侧的“已链接”标题下以及我上面评论中的链接。
【解决方案2】:

编译器不能确定该类不是在另一个编译单元中派生的,因此它必须确保调用正确地依赖于实例的运行时类型。

如果它使用 vtable 来解析虚拟调用,那么将创建一个 vtable。如果使用其他实现,则将使用该机制。


旧版本: 由于编译器无法确定该类不会在另一个编译单元中派生,因此将创建一个 vtable。

【讨论】:

  • 编译器将设置机制以使虚拟调用按标准要求工作。那台机器可能不是 vtable。
【解决方案3】:

答案是编译器必须生成一个 v-table。要了解为什么要考虑:

class B : public A
{
    void foo() { do something interesting }
}

还有其他地方:

void bar (A& obj)
{
obj.foo()
}

当然可以将 B 类型的对象传递给bar(),然后B::foo() 将被调用。对所有多态类始终使用虚拟析构函数是一种很好的编程习惯,因为它允许多态删除 A。在我们的例子中,obj 的类型为 B

void bar2 (A& obj)
{
delete obj;
}

可能不会像预期的那样运行,因为 B 的析构函数永远不会被调用。

【讨论】:

  • delete obj; 格式不正确
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-10-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多