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