2012-04-23 53 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。虛擬析構函數的行爲與非虛擬行爲完全相同(即虛擬和直接調用調用相同的函數),或者您得到未定義的行爲。所以你不能通過將非虛擬析構函數改爲虛擬函數來「做出糟糕的事情」。

但是,它可以暴露由代碼的其他部分引起的錯誤,即。當你不小心覆蓋了對象的虛擬表格指針時。

相關問題