C ++析构函数作为虚函数?

时间:2011-06-22 02:32:31

标签: c++ destructor virtual-functions

我刚才读到,将C ++析构函数实现为虚函数是一种很好的做法[1]。为什么会这样?这是一般的良好做法吗?如果没有,在什么条件/情况下,析构函数可以成为虚函数?

参考

  1. https://www.blackhat.com/presentations/bh-usa-07/Afek/Whitepaper/bh-usa-07-afek-WP.pdf

6 个答案:

答案 0 :(得分:7)

Herb Sutter在他的文章"Virtuality."指南#4中详细讨论了这个主题“基类析构函数应该是公共的和虚拟的,或者是受保护的和非虚拟的。”

如果您的类未设计或打算用作基类,则没有理由使用虚拟析构函数声明它。

答案 1 :(得分:4)

如果基类具有析构函数并且它不是虚拟的,那么如果在基类的指针上调用delete,则不会调用任何子类的析构函数。

这可能导致内存泄漏。

class Shape
{
public:
    Shape()
    {
        cout << "Shape constructor called" << endl;
    }
    // This destructor should be virtual!
    ~Shape()
    {
        cout << "~Shape destructor called" << endl;
    }
};

class Triangle : public Shape
{
public:
    Triangle()
    {
        cout << "Triangle constructor called" << endl;
    }
     ~Triangle()
    {
        cout << "Triangle destructor called" << endl;
    }

}

int main(int argc, char* argv[])
{
     Shape* pShape = new Triangle();
     cout << "About to call delete" << endl;
     delete pShape;
}

这将导致:

  

三角构造函数叫做   形状构造函数称为   即将致电删除
  形状析构函数叫

任何应该在三角形析构函数中释放的资源现在都已泄露。

答案 2 :(得分:3)

作者:Scott Meyers撰写的有效C ++ - “赋予基类虚拟析构函数的规则仅适用于多态基类 - 设计为允许通过基类接口操作派生类类型的基类。”

如果您的基类中有任何虚函数,那么基类析构函数必须是虚拟的。

不设计为基类或不设计为多态使用的类不应声明虚拟析构函数

答案 3 :(得分:2)

当你的类有一个虚析构函数时,你就可以确保调用派生类中的析构函数。

答案 4 :(得分:2)

可以说,如果您的整个类层次结构都是POD或者没有任何东西可供析构函数执行,那么可能会无法使用虚拟析构函数。但是,只要您希望从类派生其他类,希望通过指针/引用到基础多态地使用它们,您仍然会有虚函数,所以添加一个很少的开销虚拟析构函数,你永远不知道谁会继承你。只要任何派生类需要一个非平凡的析构函数并且可以通过指向base的指针引用,那么必须具有虚拟析构函数。

经验法则:如果您有任何虚函数,请添加虚拟析构函数。

(这里的要点是,如果你有 no 虚函数,那么将无法以多态方式使用派生类,因此非法子类不太可能需要非琐碎的破坏将通过基类指针删除。它仍然可以完成,它的可能性更小。)

答案 5 :(得分:-1)

http://blogs.msdn.com/b/oldnewthing/archive/2004/05/07/127826.aspx

在这个时代,我认为你应该将所有方法都虚拟化,然后再考虑哪些方法不需要。

好的,是的,我用Java完成了大部分的OOP。