欧美一区二区三区,国内熟女精品熟女A片视频小说,日本av网,小鲜肉男男GAY做受XXX网站

C++中有些類的析構函數也被定義為虛函數,這樣做有什么用?

林玟書2年前13瀏覽0評論

在閱讀C++項目(caffe)源碼時,發現不少基類不僅把常規的成員函數定義成虛函數(virtual),也會把析構函數定義為虛函數,稍稍思考下,這樣做的確是有原因的,本文將結合C++代碼實例嘗試探討下。

常規

隨便寫一段C++代碼作為實例,在這個例子中,我們先不把析構函數定義為虛函數:

這段代碼的邏輯很簡單,無非就是定義了兩個類:類Base的成員函數foo()為虛函數,構造函數和析構函數都是常規函數,此外它還有個public的成員變量buf。類Child則公開繼承了Base,因此它可以直接使用Base::buf——在構造函數中new了一段內存,并且在析構函數delete掉它。

Childc;

c.foo();

我們直接使用Child實例化一個對象c,調用c.foo(),此時得到如下輸出:

一切盡在預料中。

不安全的問題

雖說對象c調用foo()的輸出完全符合預計,但像上面那樣定義類仍然是非常危險的做法。在這一節我們曾討論過,父類指針可以調用派生類的重寫函數,因此下面這兩行C++代碼也是合法的,請看:

編譯這段C++代碼完全沒有問題,運行也不會報錯,輸出如下:

Baseconstruct

Childconstruct

Child::foo

Basedeconstruct

可是,從輸出信息能夠看出,派生類Child的析構函數沒有被調用,對于本例而言,new出來的buf沒有對應的delete,勢必會造成內存泄漏。

解決問題

要解決所謂的“不安全問題”,其實很簡單,按照題目說的做——將基類的析構函數也定義為虛函數就可以了,請看修改后的C++代碼:

也即盡在基類Base的析構函數前加上virtual關鍵字,其他的所有代碼都無需改動。現在再執行下面的這幾行C++代碼:

輸出如下:

顯然,此時派生類Child的析構函數也會被調用了,內存泄漏的問題倍解決了。

小結

C++中的virtual關鍵字是非常好用,也是C++程序員必須掌握的關鍵字,其實,“不安全問題”出現的原因也是簡單的:我們在靜態類型與動態綁定一節中提到過,基本上只有涉及到virtual函數時,才會發生動態綁定,此時通過對象指針(pb)調用的函數由它指向的類(Child)決定,所以此時派生類Child的析構函數會被調用。如果基類Base的析構函數不是虛函數,那么對象指針(pb)調用的函數由其靜態類型(Base)決定,也即調用的其實只是基類Base的析構函數而已。