在没有虚拟析构函数的情况下删除novtable基类的行为



据我所知,如果在接口指针(或者更具体地说,基类指针,指向派生类实例(上调用delete,而该声明没有虚拟析构函数,则生成的行为是未定义的,并且不会调用派生对象的析构函数。

class ITestInterface
{
public:
virtual void DoStuff() = 0;
}
class Test : public ITestInterface
{
public:
~Test(){};
virtual void DoStuff() {};
}
...
ITestInferface *pThing = new Test();
delete *pThing; // undefined

通常,您可以为基类定义一个虚拟析构函数,或者将其声明为私有,以防止在接口指针上调用delete。

如果您声明接口没有vtable

class __declspec(novtable) ITestInterface
{
public:
virtual void DoStuff() = 0;
}

通过接口指针删除对象现在是定义良好的行为,并调用适当的析构函数吗?我不明白为什么会这样,但有人告诉我。

__declspec(novtable)的作用是省略类的构造函数和析构函数中vtable指针的初始化。由于纯虚拟接口的vtable基本上是无用的,所以这是一种代码大小缩减技术。它只会影响构造函数中虚拟函数的可用性,所以只要你不在构造函数中进行需要虚拟调度的调用,一切都很好(无论如何,这都是个坏主意(。

然而,这个属性并没有说明它会在没有声明的情况下神奇地调用基类型析构函数virtual。仅根据文档,如果没有显式声明(或继承(的虚拟析构函数,通过指向接口的指针删除对象仍然是未定义的行为。

最新更新