虚析构函数可能有不利影响吗?

4

即使不需要,我始终带有虚析构函数。除了可能会有一点点性能损失外,如果不需要一个虚拟析构函数,是否存在可能导致内存错误或其他可怕情况的情况呢?

谢谢


1
Konrad拿了这个。一个副作用是它可能会消耗大量的二进制大小并增加编译时间,特别是当类的虚函数没有任何离线定义时。 - justin
3个回答

16

把所有类都设计成可扩展的是一个基本缺陷。大多数类并不适合被继承,如果你没有从一开始就为扩展而设计类,那么这样做没有任何意义。

这只会误导使用API的用户,让他们认为这个类可以有意义地被继承。实际上,这种情况很少发生,并且最坏的情况是毫无益处或者破坏代码。

一旦你让一个类可继承,你就必须永远保持它的接口不变,绝不能破坏(隐含的!)语义。基本上,这个类不再是你的了。

另一方面,继承本来就被高估了。除了用于公共接口(纯虚类)外,通常应该优先选择组合而非继承。

另外,更为基本的一种情况是在需要使用 POD 的代码中时,虚拟析构函数是不可取的,例如在使用 union、与 C 代码进行交互或执行特定于 POD 的优化(只有 POD 是可平面化的,这意味着它们可以被非常高效地复制)时。
关于性能开销的一个问题:存在很多小对象被创建的情况,或者在紧密的循环中创建对象的情况。在这些情况下,虚拟析构函数的性能开销可能是一个重大错误。
具有虚拟函数表的类也比没有虚拟函数表的类更加庞大,这也可能导致不必要的性能影响。
总之,没有强制将析构函数设置为虚函数的充分理由,而有一些不得不避免的理由。

7
我同意这一点。但更实际的答案可能是因为添加虚析构函数会破坏结构体的POD特性,而有许多应用程序需要根据内存内容定义对象的能力作为设计要求。 - Andy Ross
@Andy 老实说,我甚至没有想到这一点,这是一个非常好的理由,值得有一个独立的回答。 - Konrad Rudolph

2
如果您不打算从该类继承(或者该类不是用于继承的),那么声明它为虚拟的就没有意义。另一方面,如果您想以多态方式访问此类,则应该使用虚拟析构函数。
但是,确切地回答您的问题,它不会导致任何“可怕的内存错误”,并且始终将其标记为虚拟的也不会真正伤害您。
但是我认为没有理由一直使用虚拟析构函数。这取决于您自己。
此外,Herb的这篇文章对此问题进行了一些解释。

0

不,据我所知。虚析构函数的行为要么与非虚析构函数完全相同(即虚函数调用和直接调用调用相同的函数),要么会导致未定义的行为。因此,您不能通过将非虚析构函数更改为虚析构函数来“做一些可怕的事情”。

但是,它可以暴露由代码其他部分引起的错误,例如当您意外覆盖对象的虚表指针时。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接