4

即使不需要,我也总是用虚拟析构函数标记我的类。除了可能对性能造成很小的影响之外,是否存在这样一种情况:当您不需要一个虚拟析构函数时会导致内存错误或一些可怕的事情?

谢谢

4

3 回答 3

16

使所有类都可扩展是一个基本缺陷。大多数类根本不适合从中继承,如果您不预先设计用于扩展的类,那么促进这一点是没有意义的。

这只是在误导API 的用户,他们会将此作为类是有意义可继承的暗示。实际上,这种情况很少发生,不会带来任何好处,或者在最坏的情况下会破坏代码。

一旦你让一个类可以继承,你的余生就已经适应了它:你不能改变它的 interface,你绝不能破坏它的(隐式!)语义。本质上,这门课不再是你的了。

另一方面,无论如何,继承被高估了。除了用于公共接口(纯虚拟类)之外,您通常应该更喜欢组合而不是继承。

另一个不希望使用虚拟析构函数的更基本的情况是,当您拥有的代码需要POD才能工作时——例如在union.它们可以非常有效地复制)。[给安迪的帽子小费]

关于性能开销的一句话:在某些情况下会创建大量小对象,或者在紧密循环中创建对象。在这些情况下,虚拟析构函数的性能开销可能是一个严重的错误。

具有虚函数表的类也没有虚函数表的类大,这也会导致不必要的性能影响。

总而言之,没有令人信服的理由让析构函数虚拟化,也没有令人信服的理由不这样做。

于 2012-04-23T23:09:02.050 回答
2

如果您不打算从该类继承(或者如果该类不打算从该类继承),则将其声明为虚拟是没有意义的。
另一方面,如果你想多态地访问这个类,那么是的,虚拟析构函数是一件好事。

但是要准确回答您的问题,它不会导致任何“可怕的内存错误”并且一直将其标记为虚拟并不会真正伤害您。

但我认为没有理由一直使用虚拟析构函数。由你决定。

此外, Herb 的这篇文章也为这个问题带来了一些启示。

于 2012-04-23T23:10:15.083 回答
0

不,AFAIK。虚拟析构函数的行为方式与非虚拟析构函数完全相同(即虚拟和直接调用调用相同的函数),或者您得到未定义的行为。因此,您不能通过将非虚拟析构函数更改为虚拟析构函数来“做一些可怕的事情”。

但是,它可以暴露由代码的其他部分引起的错误,即。当您不小心覆盖了对象的虚拟表指针时。

于 2012-04-23T23:12:45.753 回答