我有一个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() { };
成员听起来可能是一件坏事。 (虽然在我的测试中,似乎工作正常。)
如何正确地从中获得所需的行为?
答案 0 :(得分:4)
在接口类中包含虚拟destructo应该没问题。您已经包含了另一个虚拟方法并将其调用,因此析构函数应该没有区别。
novtable
的效果是IFoo
的 vtable没有初始化。但是,没关系,因为你永远不会直接实例化IFoo
。相反,您实例化该类的后代。后代有一个vtable,如果Foo
有任何非纯虚方法,那么 vtable可以通过指向IFoo
(和IFoo
方法的指针正确初始化那Foo
没有覆盖)。来自~IFoo
的{{1}}来电是非虚拟发送,因此Foo
的vtable仍然不是必需的。