如果派生中没有数据成员,C ++仍然需要Virtual析构函数吗?

时间:2010-10-15 18:00:36

标签: c++ virtual-destructor

假设我有这段代码

class Base{
  public:
        int getVal();
  private:
         int a, b;
};

class Derived::public Base{
    public:
         void printVal();
};

int main(){
    Base *b = new Derived();
    delete b;    
}

我知道虚拟析构函数会正确删除内容,但是如果没有虚函数并且派生类中没有数据成员,那么使用基指针(没有虚拟析构函数)删除是不是很糟糕?如果这样做会发生什么?

3 个答案:

答案 0 :(得分:9)

  

使用基指针删除(没有虚拟析构函数)是不是很糟糕,即使派生类中没有虚函数也没有数据成员?

无论派生类的内容如何,​​行为都是未定义的。

  

如果这样做会怎样?

任何事情都可能发生。

答案 1 :(得分:7)

对于原始类型数据,您的示例很可能在实践中有效。事实上,产生vtable实际上可能阻碍性能(因此这里可能有一些合法用途),但 技术上未定义,根据5.3-5.4:< / p>

  

如果操作数的静态类型[   删除操作符]不同于   它的动态类型,静态类型   应该是操作数的基类   动态类型和静态类型   有一个虚拟的析构函数或者   行为未定义。

这实际上取决于你班级数据的“堆积度”,并且因为没有堆分配的成员(在你的情况下),你应该没问题,但这肯定是代码味道。

答案 2 :(得分:2)

当通过指向基类的指针创建派生对象时,需要派生类中的虚拟析构函数以正确调用派生的析构函数(多态)。

高完整性CPP规则3.3.2 为基类编写“虚拟”析构函数。 (QACPP 2116)

对齐:如果一个对象将通过指向其基类的指针被销毁,那么该基类应该有一个虚拟析构函数。如果基类析构函数不是虚拟的,则只调用基类的析构函数。在大多数情况下,析构函数应该是虚拟的,因为维护或重用可能会添加需要虚拟析构函数的派生类。

class Base {}; 
class Derived : public Base { public: ~Derived() {} }; 

void foo() {  
   Derived* d = new Derived; delete d; // correctly calls derived destructor 
} 
void boo() { 
   Derived* d = new Derived; Base* b = d; delete b; // problem! does not call derived destructor! 
}