首页 > 解决方案 > 使析构函数受保护以通过具有虚函数的基类禁用删除调用是个好主意吗

问题描述

我在一个环境中工作,我知道一个抽象基类的所有子类永远不会通过指向这个抽象基类的指针被删除。所以我认为没有必要让这个基类提供虚拟析构函数。因此,我使析构函数受到保护,这似乎可以满足我的要求。

这是一个简化的例子:

#include <iostream>

struct Base
{
    virtual void x() = 0;
protected:
    ~Base() =default;
};

struct Child: Base
{
    void x() override
    {
        std::cout << "Child\n";
    }
};

int main()
{
    // new and delete are here to make a simple example,
    // the platform does not provide them
    Child *c = new Child{};
    Base *b=c;

    b->x();
    // delete b; // does not compile, as requested
    delete c;
    return 0;
}

保护析构函数以防止不必要的基类删除就足够了,还是我在这里错过了一些重要的事情?

标签: c++

解决方案


这是一个好主意 [...]

从安全的角度来看,我的回答是明确的“不”:

考虑子类被再次继承的情况——也许是你以外的其他人这样做。该人可能会忽略您违反了良好实践Base并假设析构函数Child已经是虚拟的-并GrandChild通过指向Child...的指针删除

为了避免这种情况,你可以

  • 使析构函数Child再次成为虚拟的——所以最终,无论如何也没有任何收获。
  • 或宣布Child最终,施加相当多的限制,从任何其他角度来看,这些限制很可能毫无意义。

而且您必须为任何派生类选择其中之一。都是为了避免在对象删除时调用单个虚函数?

你多久会这样做一次?如果对象删除的频率确实是一个问题,那么请考虑再次分配和释放内存的开销。在这种情况下,只分配一次内存(足够大并且适当对齐以容纳您考虑创建的任何对象),执行新的和显式的析构函数调用,最后再次释放内存一次你已经完成了,不再需要它了。这将大大补偿虚函数调用......


推荐阅读