关于C++:如果类至少包含一个虚函数,那么声明析构函数总是必要的吗?


Is it always necessary to declare destructor as virtual, if the class contains atleast a virtual function?

本问题已经有最佳答案,请猛点这里访问。

Possible Duplicate:
When to use virtual destructors?

如果类(具有虚函数)及其继承类的所有数据成员都是非指针类型(意味着它不能保存任何动态内存),是否需要将析构函数声明为虚函数?

例子

1
2
3
4
5
6
7
8
9
10
11
12
13
class base {
    int x;
public:
    virtual void fn(){}

};

class der: public base {
    int y;
public:
    void fn(){}

};

这里我们需要一个虚拟析构函数吗?


不,这并不总是必要的。这只是一个经验法则,因此并不总是适用的。

真正的规则是:

A destructor must be declared virtual when objects of derived classes are to be deleted through base class pointers.

否则,通过基类指针删除派生类对象会调用未定义的行为。(最可能的结果是只调用基类的析构函数。)

当然,这条规则对于新手来说是一个很好的选择,因此更简单的经验法则几乎总是正确的。很可能您是通过多态类层次结构中的基类指针来管理动态创建的派生类对象,而对于非多态类层次结构,这样做的可能性非常小。


不,这是不需要的,而且一直这样做可能会损害性能。

除非实际存储派生类对象的基类指针为delete,否则不会遇到ub(未定义的行为)。因此,是否需要虚拟析构函数取决于代码实际创建和释放对象的方式,而不仅仅取决于类。

btw与基类相比,派生类是否需要任何额外的破坏并不重要——在delete应用于存储派生类对象地址的基类指针为ub的情况下,缺少虚拟破坏函数。


虚析构函数确保在有指向基类的指针时调用继承的类析构函数。

在这种特殊情况下,您不需要它,但是用户可以从der继承另一个类(让它成为foo),该类使用动态内存分配(例如)。在这种情况下,除非析构函数具有类型为foo的指针,否则不会调用该析构函数。

所以不,这不是"必要的",但是如果你已经有了一个虚拟功能(因此你已经有了一个vtable),那么也没有什么害处。如果您假定这些类将由用户继承,并且使用指向基类的指针释放,那么这是必需的。


对。

任何时候使用虚函数创建类时,都需要将析构函数也声明为虚函数。

考虑这种情况-

1
2
base *b = new der();
delete b;

因为您是在基指针上操作的,所以它不知道它实际上是子类的对象,因此永远不会调用der的析构函数。这可能会导致记忆泄漏和其他问题。