天天看點

C++構造函數虛拟化

虛拟構造函數

當你有一個指針或引用,但是不知道其指向對象的真實類型是什麼時,你可以調用虛拟函數來完成特定類型(type-specific)對象的行為。僅當你還沒擁有一個對象但是你确切地知道想要對象的類型時,你才會調用構造函數。那麼虛拟構造函數又從何談起呢?

例如假設你編寫一個程式,用來進行新聞報道的工作,一條新聞報道由文字或圖檔組成。你可以這樣管理它們:

C++構造函數虛拟化
C++構造函數虛拟化

在newsletter中使用的list類是一個标準模闆類(stl)。對象newletter不運作時就會存儲在磁盤上。為了能夠通過位于磁盤的替代物來建立newsletter對象,讓newletter的構造函數帶有istream參數是一種很友善的方法。當構造函數需要一些核心的資料結構時,它就從流中讀取資訊。此構造函數的僞代碼是這樣的:

C++構造函數虛拟化
C++構造函數虛拟化

或者,把這種技巧用于另一個獨立出來的函數叫做readcomponent,如下所示:

C++構造函數虛拟化
C++構造函數虛拟化

考慮一下readcomponent所做的工作。它根據所讀取的資料建立了一個新對象,或是textblock或是graphic。因為它能建立新對象,它的行為與構造函數相似,而且因為它能建立不同類型的對象,我們稱它為虛拟構造函數。虛拟構造函數是指能夠根據輸入給它的資料的不同而建立不同類型的對象。

虛拟拷貝構造函數

還有一種特殊種類的虛拟構造函數――虛拟拷貝構造函數――也有着廣泛的用途。虛拟拷貝構造函數能傳回一個指針,指向調用該函數的對象的新拷貝。因為這種行為特性,虛拟拷貝構造函數的名字一般都是copyself,cloneself或者是象下面這樣就叫做clone。很少會有函數能以這麼直接的方式實作它:

C++構造函數虛拟化
C++構造函數虛拟化

類的虛拟拷貝構造函數隻是調用它們真正的拷貝構造函數。是以”拷貝”的含義與真正的拷貝構造函數相同。如果真正的拷貝構造函數隻做了簡單的拷貝,那麼虛拟拷貝構造函數也做簡單的拷貝。如果真正的拷貝構造函數做了全面的拷貝,那麼虛拟拷貝構造函數也做全面的拷貝。

注意上述代碼的實作利用了最近才被采納的較寬松的虛拟函數傳回值類型規則。被派生類重定義的虛拟函數不用必須與基類的虛拟函數具有一樣的傳回類型。如果函數的傳回類型是一個指向基類的指針(或一個引用),那麼派生類的函數可以傳回一個指向基類的派生類的指針(或引用)。這不是c++的類型檢查上的漏洞,它使得又可能聲明象虛拟構造函數這樣的函數。這就是為什麼textblock的clone函數能夠傳回textblock*和graphic的clone能夠傳回graphic*的原因,即使nlcompo-nent的clone傳回值類型為nlcomponent*。

在nlcomponent中的虛拟拷貝構造函數能讓實作newletter的(正常的)拷貝構造函數變得很容易:

C++構造函數虛拟化
C++構造函數虛拟化

周遊被拷貝的newsletter對象中的整個component連結清單,調用連結清單内每個元素對象的虛拟構造函數。我們在這裡需要一個虛拟構造函數,因為連結清單中包含指向nlcomponent對象的指針,但是我們知道其實每一個指針不是指向textblock對象就是指向graphic對象。無論它指向誰,我們都想進行正确的拷貝操作,虛拟構造函數能夠為我們做到這點。

以上内容基本都來自《more effective c++》。

本文版權歸作者和部落格園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接配接,否則保留追究法律責任的權利。

http://www.cnblogs.com/luxiaoxun/archive/2012/08/12/2635344.html

繼續閱讀