條款08 別讓異常逃離析構函式

2021-08-10 21:15:53 字數 1964 閱讀 6745

總結:1.在析構函式中盡量不要有丟擲異常的事情發生,如果析構函式中丟擲了異常,析構函式應該自己捕捉這個異常,然後根據程式需要終止程式或者吞下這個異常然繼續執行程式

2.如果需要客戶對於某個操作的函式執行期間所丟擲的異常做出反應,這個時候應該將這個丟擲異常的 函式單獨寫在乙個函式中,而不是在析構函式中執行。

打眼一看這兩句話有點迷不知道幾個意思,其實這個條款的核心內容就是告訴你盡量不要讓異常發生在析構函式中。。然後舉了一堆實際應用中這種事情該如何處理的例子。

下面我就說一下書中的具體內容吧。

為什麼c++不禁止析構函式丟擲異常,但是又不鼓勵你去在析構函式中丟擲異常呢?下面舉個例子來說明(在這裡就直接用書上的例子了)

class widget

};void dosomething()

上述**在v被銷毀的時候會執行widget的析構函式,假如在第乙個widget這個析構函式中丟擲了異常(假設vector中有10個widget),情況好的話繼續執行銷毀後面的9個widget,但是同樣第二個widget的析構函式一樣會丟擲異常,現在有兩個同時作用的異常,這對於c++來說接受不了,程式肯定會出問題,要麼是結束執行,要麼是導致不明確行為,這個例子中的錯誤應該是導致不明確行為。注意這裡不是說使用容器之類的才會發生這種事情,終點強調的是只要析構函式丟擲異常,這種事情就會發生。所以說不要讓析構函式丟擲異常貌似就這麼解釋完了......

但是如果必須在析構函式中執行乙個動作(可以說是呼叫乙個函式完成一件事情),並且這個動作還會丟擲異常那麼我們應該怎麼處理呢?..很蛋疼的問題。。

看下面例子

class dbconnection

;

上面的例子是模擬資料庫鏈結的乙個例子,其中的close這個函式就相當於關閉資料庫的乙個動作。但是如果這麼寫的話就需要客戶自己去呼叫了,這樣難免不了萬一客戶忘記呼叫發生的問題,所以解決方法是用其他類來管理dbconnection的方法,那就是在其他類的析構函式中呼叫close這個方法,給出具體**來理解一下

class dbconn

};

這樣的話在dbconn物件被銷毀的時候就會自動呼叫close這個方法了,這樣就避免了使用者忘記自己呼叫所產生的問題

書中還有這麼乙個**

當然這只是演示關於兩個類物件的一定=些東西。

如果上面的防止客戶忘記呼叫的寫法順利執行close並且沒有異常那最好,可是如果close丟擲異常了怎麼辦呢?

解決方法1.在建構函式中捕捉這個方法,並且停止程式

class dbconn

} catch (...)

}};

解決方法2:在建構函式中捕捉異常,吞併,但是不結束程式

class dbconn

} catch (...)

}};

這兩個解決方式根據實際情況悠著不同的好壞。

其實這兩個方法都很一般般,因為他們無法對丟擲的異常情況進行乙個反應(可以說是看見這個異常的發生吧)。所以乙個比較好的方案就出來了

這個方案1.可以讓客戶自己呼叫這個方法,如果發生異常客戶可以有機會處理2.如果客戶沒有自己呼叫程式就自己呼叫這個方法,如果丟擲異常就記錄下來根據實際情況結束或者繼續執行程式。(返回之前的老路)

class dbconn

~dbconn()

}catch (...)

}}};

這樣寫就可以將close的呼叫責任推給客戶了,並且雙保險(客戶沒調,自己調)。雖然這個介面不太好,但是如果某個行為丟擲異常的話,而你又必須去處理這個異常,那麼這個異常必須來自析構函式外面的某個函式(意味這自己呼叫,現在對開始的第二句話有一定的理解了吧)。因為析構函式吐出異常是危險的,會導致不明確的行為發生或者程式終止。所以這麼寫還可以甩鍋給客戶,他們有機會處理異常而自己不去處理,程式出問題了,怪誰呢?真的是機制的程式設計師。。。

條款08 別讓異常逃離析構函式

問題 如果乙個類的析構函式必須執行乙個動作,而該動作可能會在失敗時丟擲異常,該怎麼辦?舉個例子,假設使用過乙個class負責資料庫連線 class dbconnection 乙個較佳策略是建立乙個用來管理dbconnection資源的dbconn類,dbconn類自己提供乙個close函式,因而賦予...

條款08 別讓異常逃離析構函式 74

比如以下例子 class widget 假設這個可能吐出乙個異常 void dosomething v在這裡被自動銷毀上面程式中,如果v開始銷毀,第乙個元素析構時可能丟擲異常,這時程式應該停止不然導致不明確的行為,但是後面的元素又要必須析構,不然會發生記憶體洩漏,就會陷入兩難境地。定義乙個dbcon...

別讓異常逃離析構函式

c 中並不禁止析構函式吐出異常,但是並鼓勵這樣做,看下面 當vector v被銷毀時,它有責任將其中所有的widgets銷毀並且 記憶體,而在析構第乙個元素時候,析構函式會丟擲異常,但是第二個vector的時候也會丟擲異常,這對於c 來說太多了。這會導致程式不明確的行為。c 不喜歡析構函式吐出異常。...