2012-04-23 51 views
4

我总是用虚拟析构函数标记我的类,即使它不需要。除了可能会有小的性能下降之外,还有一种情况,当你不需要虚拟析构函数时会导致内存错误或者可怕的事情?虚拟析构函数可以是一件坏事吗?

感谢

+1

Konrad采取了这个。 *一个*副作用是它可以消耗大量的二进制大小并增加编译时间,特别是当没有一个类的虚拟外行定义时。 – justin 2012-04-23 23:25:08

回答

16

这是一个根本缺陷,使各阶层扩展。大多数类别仅仅是不适合被继承,如果您没有为扩展预先设计类,那么便于这个是没有意义的。

这只是误导您的API的用户谁会将此作为暗示该类可以有意义地继承。事实上,这种情况很少出现,并且不会带来任何好处,或者在最坏的情况下破坏代码。

一旦你做出一个类继承,你用它解决你的余生:你不能改变它的界面,你绝不能打破(隐含!)语义它。本质上,这个班不再是你的。

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

另一个更基本的情况下的虚拟析构函数是不希望的是当你有的代码需要一个​​工作 - 例如在一个union使用它时,与C语言代码的接口或执行时POD-特定的优化时作为(只有POD是blittable,意味着它们可以非常有效地复制)。 [帽尖安迪]

甲字约性能开销:存在其中许多小对象被创建的情况下,或者在紧凑循环中创建的对象。在这些情况下,虚拟析构函数的性能开销可能是一个严重错误。

具有虚拟功能表的类也是比没有类更大的,这也会导致不必要的性能影响。

总而言之,没有令人信服的理由让析构函数变成虚拟的,并且一些令人信服的理由不是。

+7

我同意所有这一切。但更实际的答案可能是因为添加虚拟析构函数会破坏结构的POD性,并且有许多应用程序能够根据其内存内容定义对象,这是设计需求。 – 2012-04-23 23:14:00

+0

@Andy老实说,我甚至没有想到这一点,这是一个很好的理由,值得自己回答。 – 2012-04-23 23:14:57

+0

@我现在已经添加了这个。 – 2012-04-24 07:07:02

2

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

但是要准确回答你的问题,它不会导致任何“可怕的记忆错误”,并且始终将它标记为虚拟并不能真正伤害你。

但我没有理由一直使用虚拟析构函数。随你便。

另外,由Herb发布的this带来了一些事情。

0

不,AFAIK。虚拟析构函数的行为与非虚拟行为完全相同(即虚拟和直接调用调用相同的函数),或者您得到未定义的行为。所以你不能通过将非虚拟析构函数改为虚拟函数来“做出糟糕的事情”。

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

相关问题