c++ - 什么时候以及为什么不应该将基类中的析构函数定义为虚拟的?

标签 c++ virtual-destructor

下面的这个例子说明了如何防止派生类被复制。它基于一个基类,其中复制构造函数和复制赋值运算符都被声明为 private

class Uncopyable
{
protected:
   // allow construction and destruction of derived objects...
   Uncopyable() {}
   ~Uncopyable() {}

private:
   // but prevent copying...
   Uncopyable(const Uncopyable&);
   Uncopyable& operator=(const Uncopyable&);
};

我们可以使用这个类,结合私有(private)继承,使类不可复制:

class derived: private Uncopyable
{...};

请注意类 Uncopyable 中的析构函数未声明为 virtual。

我以前学过

  • 基类中的析构函数应该是虚拟的
  • 不应将非基类中的析构函数设为virtual

在此示例中,Uncopyable 的析构函数不是virtual,但它是从中继承的。这似乎与我之前学到的智慧背道而驰。

何时以及为何不应将基类中的析构函数定义为virtual

最佳答案

如果您可能尝试通过基类型的指针释放派生类型的对象,则基类析构函数只需要是。因此,如果您仅私有(private)地而不是公开地继承基类,就像Uncopyable中的情况一样,那么您不需要担心放入一个virtual 析构函数,因为当使用私有(private)继承时,您无法获得指向派生对象的指针并将其存储在指向基类型的指针中。

另一个例子可能是,如果你要使用像这样的混合类,它使一个类跟踪对象分配的数量,其中混合类继承自以获取行为但不进行多态处理:

template <typename T> class Counter {
public:
    Counter() { ++numInstances; }
    Counter(const Counter&) { ++numInstances );
    ~Counter() { --numInstances; }

    static unsigned getNumInstances() { return numInstances; }

private:
    static unsigned numInstances;
}
template <typename T> unsigned Counter<T>::numInstances = 0;

更一般地说,当使用静态多态性时,您不需要虚拟析构函数,因为您永远不会使用指向基类型的指针以多态方式处理类。您仅使用指向派生类型的指针。

可能还有一些其他情况我没有在这里介绍,但这两个(私有(private)继承、mixin 类和静态多态性)涵盖了不需要虚拟析构函数的大部分空间。

关于c++ - 什么时候以及为什么不应该将基类中的析构函数定义为虚拟的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7005084/

相关文章:

c++ - 是否有等同于 gsl_multifit_wlinear() 的 Eigen C++ 库?

c++ - 如何从没有虚拟析构函数的类派生?

c++ - 如果基类析构函数是虚拟的,是否需要派生类析构函数定义?

c++ - 如果派生类不包含静态数据,我是否需要为派生类实现自己的析构函数?

c++ - 如何通过位掩码存储和检索 3 位数字?

c++ - execvp( command.argv[0], command.argv) 后程序停止

c++ - 如何初始化 OpenSSL BIO 对象?

c++ - fstream 文件为空(简单的小代码)

c++ - 具有虚拟析构函数的基类的子类中的默认析构函数

c++ - 基础和派生虚拟析构函数的影响