我有一个 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;
}
Run Code Online (Sandbox Code Playgroud)
因为IFoo没有虚拟析构函数,所以Foo永远不会调用具体析构函数。
输出:
FooDo()
Run Code Online (Sandbox Code Playgroud)
期望输出:
FooDo()
~Foo()
Run Code Online (Sandbox Code Playgroud)
但是,在MSDN 中,对于在声明的接口类中调用函数有一个可怕的警告novtable。“如果您尝试实例化标有 novtable 的类,然后访问类成员,您将收到访问冲突 (AV)。” 因此,添加virtual ~IFoo() { };成员听起来可能是件坏事。(虽然在我的测试中,它似乎工作正常。)
如何正确地从中获得所需的行为?
在你的接口类中包含一个虚拟析构函数应该没问题。您已经包含了另一个虚拟方法并调用了它,因此析构函数应该没有什么不同。
的效果novtable是vtableIFoo没有被初始化。不过没关系,因为你从来没有直接实例化IFoo. 相反,您实例化该类的后代。后代有一个 vtable,并且该vtable 使用指向方法的指针正确初始化Foo(并且IFoo,如果IFoo有任何Foo不覆盖的非纯虚拟方法)。对~IFoofrom Fooinside的调用是非虚拟调度,因此IFoo仍然不需要 still的 vtable 。
| 归档时间: |
|
| 查看次数: |
548 次 |
| 最近记录: |