novtable接口中的虚析构函数是否可行?

3

我有一个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个回答

6
在接口类中包含虚析构函数应该没问题。您已经包含了另一个虚方法并调用了它,因此析构函数也不会有任何不同。
novtable 的效果是 IFoo 的虚表不会被初始化。虽然如此,但这没有问题,因为您从未直接实例化 IFoo。相反,您实例化了一个子类。子类有一个虚表,并且该虚表得到正确的初始化,其中包括指向 Foo 方法(以及 IFoo,如果 IFoo 有任何非纯虚方法,而 Foo 没有覆盖它们)的指针。从 Foo 中调用 ~IFoo 是一个非虚分派,因此仍然不需要 IFoo 的虚表。

虽然我调用了一个虚函数FooDo,但它是纯虚函数并没有实现;而析构函数不能是纯虚函数,必须有一个实现(即使是空的)。我的担心是这种差异会符合“调用类成员”的标准。 - PaulH

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接