C++ 每个类都应该有一个虚拟析构函数吗?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/353817/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 14:51:36  来源:igfitidea点击:

Should every class have a virtual destructor?

c++virtual-destructor

提问by Motti

Java and C# support the notion of classes that can't be used as base classes with the finaland sealedkeywords. In C++ however there is no good way to prevent a class from being derived from which leaves the class's author with a dilemma, should every class have a virtual destructor or not?

Java 和 C# 支持不能使用finalandsealed关键字作为基类的类的概念 。然而,在 C++ 中,没有好的方法可以防止派生一个类,这让类的作者陷入两难境地,每个类都应该有一个虚拟析构函数吗?



Edit:Since C++11 this is no longer true, you can specify that a class is final.

编辑:由于 C++11 这不再正确,您可以指定一个类是final.



On the one hand giving an object a virtual destructor means it will have a vtableand therefore consume 4 (or 8 on 64 bit machines) additional bytes per-object for the vptr.

一方面,给一个对象一个虚拟析构函数意味着它将有一个vtable并因此为vptr.

On the other hand if someone later derives from this class and deletes a derived class via a pointer to the base class the program will be ill-defined (due to the absence of a virtual destructor), and frankly optimizing for a pointer per object is ridiculous.

另一方面,如果后来有人从这个类派生并通过指向基类的指针删除派生类,程序将是错误定义的(由于没有虚拟析构函数),坦率地说,为每个对象优化一个指针是荒谬的。

On the gripping hand having a virtual destructor (arguably) advertises that this type is meant to be used polymorphically.

在具有虚拟析构函数的抓手上(可以说)宣传这种类型旨在以多态方式使用。

Some people think you need an explicit reason to not use a virtual destructor (as is the subtext of this question) and others say that you should use them only when you have reason to believe that your class is to be derived from, what do youthink?

有些人认为,你需要一个明确的理由不使用虚拟析构函数(如的潜台词这个问题)和其他人说,只有当你有理由相信,你的类是从派生你应该使用它们,有什么事思考?

采纳答案by jalf

The question is really, do you want to enforcerules about how your classes should be used? Why? If a class doesn't have a virtual destructor, anyone using the class knows that it is not intended to be derived from, and what limitations apply if you try it anyway. Isn't that good enough?

问题是真的,你想强制执行关于如何使用你的类的规则吗?为什么?如果一个类没有虚拟析构函数,任何使用该类的人都知道它不是要派生自的,并且如果您尝试它,则会受到哪些限制。这还不够好吗?

Or do you need the compiler to throw a hard error if anyone daresto do something you hadn't anticipated?

或者,如果有人胆敢做你没有预料到的事情,你是否需要编译器抛出一个硬错误?

Give the class a virtual destructor if you intend for people to derive from it. Otherwise don't, and assume that anyone using your code is intelligent enough to use your code correctly.

如果您打算让人们从中派生,则为该类提供一个虚拟析构函数。否则不要,并假设任何使用您代码的人都足够聪明,可以正确使用您的代码。

回答by Johannes Schaub - litb

Every abstract class should either have a,

每个抽象类都应该有一个,

  • protected destructor, or,
  • virtual destructor.
  • 受保护的析构函数,或者,
  • 虚拟析构函数。

If you've got a public non-virtual destructor, that's no good, since it allows users to delete through that pointer a derived object. Since as we all know, that's undefined behavior.

如果您有一个公共的非虚拟析构函数,那就不好了,因为它允许用户通过该指针删除派生对象。因为众所周知,这是未定义的行为。

For an abstract class, you already need a virtual-table pointer in the object, so making the destructor virtualdoesn't (as far as I'm aware) have a high cost in terms of space or runtime performance. And it has the benefit that derived classes automatically have their destructors virtual(see @Aconcagua's comment). Of course, you can also make the destructor protected virtualfor this case.

对于抽象类,您已经在对象中需要一个虚拟表指针,因此创建析构函数virtual(据我所知)在空间或运行时性能方面不会有很高的成本。它的好处是派生类会自动拥有它们的析构函数virtual(请参阅@Aconcagua 的评论)。当然,您也可以protected virtual为这种情况制作析构函数。

For a non-abstract class not intended to be deleted through a pointer to it, I don't think there's good reason to have a virtual destructor. It would waste resources, but more importantly it would give users a wrong hint. Just think about what weird sense it would make to give std::iteratora virtual destructor.

对于不打算通过指向它的指针删除的非抽象类,我认为没有充分的理由使用虚拟析构函数。它会浪费资源,但更重要的是它会给用户一个错误的提示。想想给std::iterator一个虚拟析构函数会有什么奇怪的意义。

回答by Nemanja Trifunovic

No! Virtual destructors are used only when a object of a derived class is deleted through a base class pointer. If your class is not intended to serve as the base in this scenario, don't make the destructor virtual - you would be sending a wrong message.

不!仅当通过基类指针删除派生类的对象时才使用虚拟析构函数。如果您的类不打算在这种情况下用作基础,请不要将析构函数设为虚拟 - 您将发送错误消息。

回答by Paolo Tedesco

Check this article from Herb Sutter:

查看Herb Sutter 的这篇文章

Guideline #4: A base class destructor should be either public and virtual, or protected and nonvirtual.

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

回答by Evan Teran

I would "no" to the general question. Not everyclass needs one. If you can know that the class should never be inherited from, then there is no need to incur the minor overhead. But if there is a chance, be on the safe side and put one in there.

对于一般性问题,我会“不”。不是每个班级都需要一个。如果您知道该类不应该被继承,那么就没有必要产生较小的开销。但是如果有机会的话,为了安全起见,把一个放在那里。

回答by shurli pataka

Base class becomes abstract class, when it contains at least one pure virtual function. If Base does not have a virtual destructor and Derived (derived from Base) does, then you can safely destroy a Derived object through a Derived object pointer but not through a Base object pointer.

当基类至少包含一个纯虚函数时,它就成为抽象类。如果 Base 没有虚拟析构函数而 Derived(派生自 Base)有,那么您可以通过 Derived 对象指针安全地销毁 Derived 对象,但不能通过 Base 对象指针。

回答by Patrick Hogan

I'll add that there have been times when I have scratched my head for a while on destructors not getting called when I forgot a virtual in the parent or child class. I guess I know to look for that now though. :)

我要补充的是,当我忘记父类或子类中的虚拟时,有时我会因为没有调用析构函数而挠头。不过我想我现在知道要去找那个了。:)

Someone might argue that there are times the parent class does something in its destructor that a child should not do... but that's probably an indicator of something wrong with your inheritance structure anyway.

有人可能会争辩说,有时父类在其析构函数中做了一些子类不应该做的事情……但这可能表明您的继承结构有问题。