1

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

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

关于这个 __declspec 扩展属性的MSDN 文章说,添加这个人将删除构造和析构函数 vtable 条目,从而导致“显着减少代码大小”(因为 vtable 将被完全删除)。

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

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

所以我想总结一下:

  • 对于纯虚拟接口,编译器是否会删除 vtable,或者我在这里错过了一些基本的东西?
  • MSDN 文章在说什么?
4

2 回答 2

2

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

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

于 2009-03-12T01:11:29.953 回答
1

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

于 2009-03-12T09:02:07.293 回答