在novtable接口中是虚拟析构函吗?

时间:2012-05-17 17:39:28

标签: c++

我有一个Visual Studio 2008 C ++ 03项目,其中我有一个声明为_declspec( novtable )的接口类。例如:

class _declspec( novtable ) IFoo
{
public:
    virtual void FooDo() const = 0;
};

class Foo : public IFoo
{
public:
    ~Foo() { printf( "~Foo()\r\n" ); };
    void FooDo() const { printf( "FooDo()\r\n" ); };
};

int main( int argc, char* argv[] )
{
    IFoo* foo = new Foo();
    foo->FooDo();
    delete foo;
    return 0;
}

因为IFoo没有虚析构函数,所以永远不会调用具体的Foo析构函数。

输出:

FooDo()

期望的输出:

FooDo()
~Foo()

但是,在MSDN中,对于在声明为novtable的接口类中调用函数存在严重警告。 " 如果您尝试实例化一个标有novtable的类,然后访问一个类成员,您将收到一个访问冲突(AV)。"因此,添加virtual ~IFoo() { };成员听起来可能是一件坏事。 (虽然在我的测试中,似乎工作正常。)

如何正确地从中获得所需的行为?

1 个答案:

答案 0 :(得分:4)

在接口类中包含虚拟destructo应该没问题。您已经包含了另一个虚拟方法并将其调用,因此析构函数应该没有区别。

novtable的效果是IFoo vtable没有初始化。但是,没关系,因为你永远不会直接实例化IFoo。相反,您实例化该类的后代。后代有一个vtable,如果Foo有任何非纯虚方法,那么 vtable可以通过指向IFoo(和IFoo方法的指针正确初始化那Foo没有覆盖)。来自~IFoo的{​​{1}}来电是非虚拟发送,因此Foo的vtable仍然不是必需的。