什么时候你的析构函数是虚拟的?

可能重复:
何时使用虚拟析构函数?

什么时候你的C ++对象的析构函数是virtual

  1. 当至less有一个类方法是虚拟的时候,你需要虚拟析构函数。

这是因为虚拟方法的原因是你想使用多态。 这意味着你将调用一个基类指针的方法,并且你需要最派生的实现 – 这是多态的完整点。

现在,如果您没有虚拟析构函数,并且通过指向基类的指针调用析构函数,则最终调用基类析构函数。 在这种情况下,你希望多态性也可以在你的析构函数上工作,例如通过调用你的基类的析构函数来调用你最基本类的析构函数而不是你的基类。

 class A { virtual void f() {} ~A() {} } class B : public A { void f() {} ~B() {} } A * thing = new B(); thing->f(); // calls B's f() delete thing; // calls ~A(), not what you wanted, you wanted ~B() 

具有〜A()虚拟转向多态性

 virtual ~A() {} 

所以当你现在打电话

 delete thing; 

〜B()将被调用。

当您将类devise为一个接口时,您将声明虚拟析构函数,例如您期望它被扩展或实现。 在这种情况下,一个好的做法是有一个接口类(在Java接口的意义上)与虚拟方法和虚拟析构函数,然后有具体的实现类。

你可以看到,STL类没有虚拟析构函数,所以它们不应该被扩展(例如std :: vector,std :: string …)。 如果扩展std :: vector,并且通过指针或引用调用基类的析构函数,则绝对不会调用可能导致内存泄漏的专用类析构函数。

来自Stroustrup的C ++风格和技巧常见问题解答 :

那么我应该什么时候声明一个析构函数? 每当课程至less有一个虚拟function。 具有虚函数表示一个类是为了作为派生类的接口,当它是时,派生类的对象可以通过指向基类的指针被销毁。

关于什么时候你的析构函数应该在C ++ FAQ上是虚拟的 。 (感谢Stobor)

什么是虚拟会员? 从C ++ FAQ :

[20.1]什么是“虚拟成员函数”?

从OO的angular度来看,它是C ++最重要的特性之一:[6.9],[6.10]。

虚函数允许派生类来replace基类提供的实现。 编译器确保每当有问题的对象实际上是派生类时,总是调用replace,即使对象是由基指针而不是派生指针访问的。 这使基类中的algorithm可以在派生类中被replace,即使用户不知道派生类。

派生类可以完全replace(“覆盖”)基类成员函数,或派生类可以部分replace(“扩充”)基类成员函数。 后者是通过让派生类成员函数调用基类成员函数来实现的,如果需要的话。

我最近得出结论,完全正确的答案是这样的:

准则4:基类析构函数应该是public和virtual,或者是protected和nonvirtual。

当然, 赫伯·萨特(Herb Sutter)给出了他的主张的基本原理 。 请注意,他确实超越了“当有人通过基类指针删除派生类对象”和“如果您的类具有任何虚函数时使您的析构函数为虚拟”的常见答案。

如果你会(甚至可能)通过基类指针销毁派生类的对象,你需要一个虚拟析构函数。

我采取的方法是,如果我要从一个类的全部派生,那么它应该有一个虚拟的析构函数。 在虚拟析构函数的性能问题上,我写的代码中实际上没有这样的情况,并且即使它现在不是真正需要的,也可能在将来修改类时最终需要它。

基本上说:除非你有一个好的,经过深思熟虑的理由,否则虚拟所有基类的析构函数。

这只是另一个经验法则,但它是一个让你不犯以后的错误。

总是。

除非我真的关心vtable的存储和性能开销,否则我总是把它变成虚拟的。 除非你有一个静态分析工具来validation你的析构函数在正确的情况下是虚拟的,否则不值得犯错误,在需要的时候不能创build虚拟析构函数。

基类对象应该有一个虚拟的析构函数,当基类有必要做自己的清理。 这就是说,如果已经在基类中分配了资源,那么基类就需要清理,通过声明它的析构函数为虚拟的,保证这个清理将被完成(假设你已经正确地写入了清理)。

通常,方法可以在基类中被虚拟定义,这将允许派生类覆盖虚方法,实现它们自己派生的特定实现。 我觉得用一个简单的例子就可以清楚地certificate这一点。 假设我们有一个基类“Shape”,现在所有派生类都可能被要求具有绘制的能力。 “Shape”对象不知道如何绘制派生类,因此在“Shape”类中我们定义了一个虚拟绘图函数。 即(虚拟void draw();)。 现在在每个基类中,我们可以重写这个函数,实现特定的绘图代码(即一个正方形与一个圆圈不同)。