【问题标题】:DECLSPEC_NOVTABLE on pure virtual classes?纯虚拟类上的 DECLSPEC_NOVTABLE?
【发布时间】:2009-03-12 00:58:19
【问题描述】:

这可能是习惯性的编程冗余。我注意到在标题中定义的一堆接口上的 DECLSPEC_NOVTABLE ( __declspec(novtable) ):

struct DECLSPEC_NOVTABLE IStuff : public IObject
{
    virtual method1 () = 0;
    virtual method2 () = 0;
};

此 __declspec 扩展属性上的 MSDN article 表示添加此人将删除构造和析构函数 vtable 条目,从而导致“显着减少代码大小”(因为 vtable 将被完全删除)。

这对我来说没有多大意义。这些家伙是纯虚拟的,为什么编译器不默认这样做呢?

文章还说,如果您这样做,然后尝试实例化其中一件事情,您将遇到运行时访问冲突。但是当我用一些编译器(有或没有 __declspec 扩展)尝试这个时,它们不能编译(正如我所预料的那样)。

所以我想总结一下:

  • 编译器是否会剔除 vtable 而不管纯虚拟接口,还是我在这里遗漏了一些基本内容?
  • MSDN 文章在谈论什么?

【问题讨论】:

    标签: c++ visual-c++ msdn pure-virtual


    【解决方案1】:

    编译器删除了对 vtable 的 唯一引用,这本来是在类的构造过程中进行的。因此,链接器可以将其优化掉,因为代码中不再有对它的引用。

    顺便说一句,我养成了将空构造函数声明为protected 的习惯,并且还使用了Microsoft 的扩展abstract 关键字,以避免在运行时出现访问冲突。这样,编译器就会在编译时捕获问题(因为只有基类可以通过受保护的构造函数实例化接口)。派生类当然会在构造期间填充vtable。

    【讨论】:

    • 为什么不避免运行时访问冲突?知道某人何时实例化纯虚拟类不是很好吗?对此还是有点模糊;)。
    【解决方案2】:

    对于愚蠢的编译器/链接器来说,这有点牵强。编译器不应插入对此 vtable 的任何引用,因为很明显不需要此 vtable。编译器也可以用链接器消除 vtable 的方式标记引用,但这当然更复杂。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-11-21
      • 2011-06-04
      • 2013-10-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多