【问题标题】:pure virtual class, only 1 derived class, still vtable?纯虚拟类,只有 1 个派生类,还是 vtable?
【发布时间】:2012-03-26 19:41:54
【问题描述】:

我的问题很简单,如果你有一个纯虚拟类(接口),但由于当前的活动构建,只编译了 1 个派生类,还会创建一个 vtable 吗?

class Foo
{
    virtual void bar() = 0;
}
#if 1
class Foo_1 : public Foo
{
void bar() {cout<<"foo_1";}
}
#else
class Foo_2 : public Foo
{
void bar() {cout<<"foo_2";}
}
#endif

他们(据我所知)在这种情况下不需要 vtable。

那么这会得到优化还是你仍然会得到 vtable 的开销?

谢谢

【问题讨论】:

  • 你认为指向 virtual 函数的指针在哪里......?
  • 假设编译器在这里优化了一些东西,现在我添加一个带有class Nasty : public Foo { void bar() {} };nasty.cpp 文件。
  • @ R. Martinho Fernandes,你的说法是对的,但这是在编译时就知道的......所以如果它们是从 Foo 派生的多个类,是的,它们应该是一个 vtable。但是如果(就像我的情况)他们只是一个,你真的不需要它吗?还是你?
  • @moiself 无论如何,只有一种方法可以知道,那就是编译和查看。
  • 每个类(而不是每个对象)只有一个 vtable,因此内存开销不应成为问题。虚函数调用仅在通过指向基类的指针调用时使用 vtable,因此如果您只有一个派生类 (Foo_1) 并且只有 Foo_1 的对象,那么它们就没有开销。

标签: c++ vtable


【解决方案1】:

这是一种潜在的链接时优化(但显然不能在编译时进行)。

【讨论】:

    【解决方案2】:

    你仍然会得到 vtable。毕竟,编译器不知道类Foo 是否会在其他翻译单元中使用。或者,您可能会将其打包为一个库,而其他一些用户将从Foo 派生;再次,编译器不知道先验。

    【讨论】:

    • 翻译单元在链接时间代码生成时是一种过时的术语。
    • @ConfusedSushi 翻译单元是官方术语。我怀疑这算作过时了。
    • 翻译单元必须与翻译而非优化有关。优化是实现定义的,并且允许编译器/链接器优化 vtable。
    • 编译器只有在知道代码的行为不会改变(当然,除了它的性能特征之外)的情况下才应该进行优化。通常,它必须保持对标准允许的任何内容的支持。诚然,许多编译器都有允许您超出标准的开关,并且编译器可能有一个“假设我现在知道的所有类都是我将永远知道的”开关并不是不可想象的,但它应该'默认情况下不启用。
    【解决方案3】:

    你可能会得到 vtable 的开销,因为类总是可以被子类化(如果你的示例代码的内容在标题中):

    class Foo_3 : public Foo_1 {
         void bar() { Foo_1::bar(); ... }
    }
    

    如果所有的代码都在同一个翻译单元中,编译器也许能把它全部弄清楚。

    【讨论】:

      猜你喜欢
      • 2015-10-24
      • 2013-10-07
      • 1970-01-01
      • 2011-06-04
      • 2018-01-05
      • 1970-01-01
      • 2013-11-04
      • 2015-10-23
      相关资源
      最近更新 更多