2010-02-27 100 views
4

我有一個C++類(在一個dll項目中),其成員變量是boost :: shared_ptrs到其他類的對象。將它們分配給類構造函數還是有一個單獨的init()函數可以實現這一點,這會更好嗎?在構造函數中分配共享ptrs(boost),單元測試

我假設內部boost :: shared_ptr指針T的默認值爲NULL。所以如果我在構造函數裏什麼都不做,boost :: shared_ptr的get()在調用Init()函數之前返回NULL。

另外,如果在賦值語句中有新的內存分配問題,應該如何捕獲異常(在Init中)還是很好地告訴調用者這個Init()來捕獲異常? boost :: shared_ptr a(new T);

是否有標準方法來模擬單元測試中的內存分配異常?並查看所有對象已正確取消分配

回答

2

我有一個C++類(在一個dll項目中),其成員變量是boost :: shared_ptrs到其他類的對象。將它們分配給類構造函數還是有一個單獨的init()函數可以實現這一點,這會更好嗎?

在構造函數中完成所有事情通常更好。
有一個被稱爲afterwords的init()函數意味着該對象在構造後是無效的,因此您需要保留一個狀態標誌來指示init()是否已被調用,並在調用任何公用方法時檢查該標誌並做一些適合未初始化的對象的東西

我假設在boost :: shared_ptr裏面的T指針的默認值是NULL。所以如果我在構造函數裏什麼都不做,boost :: shared_ptr的get()在調用Init()函數之前返回NULL。

是:shared_ptr的默認構造函數將它初始化爲NULL。

而且,當有新的內存分配問題的賦值語句,我應該捕獲該異常(以初始化)中的一個或者是好講這個初始化(調用者)來捕捉那會發生什麼例外? boost :: shared_ptr a(new T);

如果你有一個構造函數:然後就是已經建成將正確地銷燬(通過析構函數),而unitialised對象將不會被感動了所有成員,以及當前對象的內存將被釋放,就好像從未被分配過(使用初始化列表的另一個很好的理由)。

如果您使用init():那麼您必須捕獲異常並正確清理對象並釋放內存。根據對象的複雜程度,你可能能夠在init中做這件事(但很難做到正確)或者調用者必須這樣做。之後,您應該像構造函數拋出異常一樣執行相同的操作(這取決於使用情況)。

是否有標準方法來模擬單元測試中的內存分配異常?並看到所有的對象都被正確地解除分配

您可以使用工廠對象來分配對象。
您將工廠對象傳遞給構造函數。當你想在施工過程中模擬異常時,只需傳遞一個模擬工廠來生成適當的異常。

1

使用初始化程序列表進行成員分配。他們是首選(有時是唯一的方法)。

如果在創建對象時出現問題,請拋出異常並進行保護。或者,您將需要維護一個valid標誌,每次調用成員函數時都必須檢查該標誌,以檢查正在使用的對象是否有效。

你總是可以捕捉異常並報告它們。如果執行失敗,理想情況下你不應該拋出異常,而應該在dtor中處理它,報告並繼續前進。

1

在第一個問題上,您應該理想地使用初始化列表來確保指針是有效的。不這樣做意味着您可能必須始終檢查指針在使用前是否有效;特別是如果你把它留給呼叫代碼來呼叫init()

另一方面,它可能是你不能這樣做,如果他們只能通過調用純虛擬設置,在這種情況下,你會有使用init()方法。

在初始化時,我認爲你可以捕獲並重新拋出或者根本不捕獲。無論哪種方式,我認爲,調用者可以捕獲內存分配異常。

我可以看到爲什麼你想要嘗試在你的一個對象上調用init()來測試內存分配異常。這裏的一個方法可能是替換一個總是拋出一個調用的存根對象init()

我看不出爲什麼你想檢查共享指針的解除分配(原始指針,也許)當然,共享點指針是,雖然你能夠引用你的共享指針,根據定義,共享它,所以它不會被破壞。

也許你可以檢查引用計數或設置你的尖銳對象並(在破壞時)清除你的測試可以監控的信號量。我以某種方式錯過了這一點?

+0

感謝您的回答羅賓,我應該在單元測試時使用引用計數。我也喜歡創建存根 – Kamal 2010-02-27 15:05:19

+0

@Kamal的想法,如果任何其他初始化成員拋出,編譯器將調用任何初始化成員的析構函數。 – 2010-02-27 15:23:35

相關問題