你的析构函数何时应该是虚拟的?

Mic*_*hou 42 c++ virtual-destructor

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

您的C++对象的析构函数何时应该virtual

ste*_*anB 52

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

这是因为虚方法的原因是你想使用多态.这意味着您将在基类指针上调用一个方法,并且您需要最多派生的实现 - 这是多态性的全部要点.

现在,如果您没有虚拟析构函数并通过指向基类的指针调用析构函数,则最终调用基类析构函数.在这种情况下,您希望多态性也可以在析构函数上运行,例如,通过在基类上调用析构函数,您希望最终调用最派生类的析构函数而不是基类.

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()
Run Code Online (Sandbox Code Playgroud)

让~A()虚拟转向多态

virtual ~A() {}
Run Code Online (Sandbox Code Playgroud)

所以,当你现在打电话

delete thing;
Run Code Online (Sandbox Code Playgroud)

~B()将被调用.

当您将类设计为接口时,您将声明虚拟析构函数,例如,您希望将其扩展或实现.在这种情况下,一个好的做法是使用虚拟方法和虚拟析构函数创建一个接口类(在Java接口的意义上),然后具有具体的实现类.

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


luk*_*uke 33

来自Stroustrup的C++风格和技巧FAQ:

那么什么时候我应该声明一个析构函数虚拟?每当类具有至少一个虚函数时.具有虚函数表示类意味着充当派生类的接口,并且当它是时,派生类的对象可以通过指向基类的指针来销毁.

关于何时应该在C++ FAQ上虚拟析构函数的大量其他信息.(感谢Stobor)

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

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

从面向对象的角度来看,它是C++最重要的一个特性:[6.9],[6.10].

虚函数允许派生类替换基类提供的实现.只要有问题的对象实际上是派生类,编译器就会确保始终调用替换,即使对象是由基指针而不是派生指针访问的.这允许在派生类中替换基类中的算法,即使用户不知道派生类.

派生类可以完全替换("覆盖")基类成员函数,或者派生类可以部分替换("扩充")基类成员函数.如果需要,后者是通过使派生类成员函数调用基类成员函数来实现的.

  • 确切地说,什么时候没有虚函数的父类的子类定义了一个需要清理但不包含在父元素中的成员?缺少虚拟析构函数意味着"删除父级"不会调用子类的析构函数... (2认同)
  • 在那种情况下,Stobor,实例化派生类几乎没有意义.没有dynamic_cast就无法访问派生类的方法,这意味着对象类型的知识.这些知识也可以在析构函数之前用于dynamic_cast.当然,虚拟方法的事情只是一个经验法则.毫不奇怪你的人为的例子在其中射出了一个漏洞 (2认同)

Reu*_*nen 5

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

准则#4:基类析构函数应该是公共的和虚拟的,或者是受保护的和非虚拟的.

当然,赫伯萨特给出了他的主张的理由.请注意,他确实超出了通常的答案"当有人通过基类指针删除派生类对象时",并且"如果你的类有任何虚函数,则使你的析构函数为虚拟".