C++異常類設計

一【概述】

在平時的開發過程中,我發現很多程序員都不願意使用異常類。問他們爲什麼不用,回答無非有以下幾種:1. 使用異常類太麻煩了,沒有返回錯誤碼的方式方便;2. 已經習慣C語言中使用以返回錯誤碼的方式來處理異常情況了;3. C++的異常類的代碼編寫加重了程序員負擔,提高了開發成本;4. C++代碼中有時需要調用一些C庫,而C語言是返回錯誤碼的,所以爲了統一風格也就將就着使用返回值了。那麼,異常類跟傳統的返回錯誤碼的方式相比,有哪些優點?異常類應該怎樣設計呢?本文將圍繞這兩點進行一些思考。

二【C++異常類說明】

我們在平時編寫代碼時,一般很難將異常的情況全部考慮周全,主觀上是因爲這取決於開發人員的個人水平、經驗或對業務的熟悉程度,不過從客觀上來說也是因爲錯誤的場景一般會遠遠多於正常的處理情況,很難一次就全部想到,尤其是在大型複雜的系統中,只能在日後不斷進行修補維護。針對這些問題,C++中引入了異常的概念,目的是用來加強系統在出現異常情況時的處理能力,提高系統的魯棒性、穩定性和可用性。

  1. C++異常類與返回值最大的不同在於當它被拋出的時候,它會強迫調用者去處理,否則默認就會終止進程。這是合理的,因爲當程序處於一個非正常狀態並且不能從中恢復,那就應該馬上終止,否則很有可能耗費更多的系統資源甚至造成更大損失。
  2. C++異常類可以將對同一類異常進行集中處理。這樣可以保證良好的代碼結構,同時也讓你集中精力編寫正常的業務邏輯代碼。
  3. 相對於C語言裏面一個蒼白無力的錯誤碼,C++異常類可以包含豐富的異常信息,如:錯誤描述、錯誤碼、發生異常時的上下文信息等等。這可以讓開發人員更加方便、精準的推斷異常的原因,從而更加到位的處理異常。
  4. 將異常看做一個對象,這也符合面向對象的設計理念。

但是C++的異常機制並沒有像JAVA那樣純粹,使得C++異常在使用時可能會導致一些別的錯誤。這體現在一下幾個方面:

  1. C++的異常規格(exception specification)並不是強制性的,而JAVA則一定會對異常規格進行靜態檢查。也就是說當C++函數需要拋出異常的時候,你可以選擇在函數說明時使用異常規格描述,也可以不使用。因爲在C語言裏面是沒有異常規格的,同時C++又要與C兼容,所以C++無法強制使用異常規格,否則就無法調用C函數了。不過,最致命的還是異常規格有時可能會有實際情況不符,即,程序在運行的時候,函數可能會拋出異常規格中沒有的異常類型,這時就會導致進程調用unexcepted()函數。默認情況下,該函數又會調用terminate(),這個函數最終會導致進程終止。這就導致異常規格形同虛設,還可能會誤導調用者,所以《C++編程規範:101條規則、準則與最佳實踐》中也指出不要使用exception specification,這會導致很多不確定的情況。
  2. C++異常會導致執行流程的跳轉,從而使得一些分配的資源沒有得到釋放。JAVA中可以通過finally來保證非內存資源得到釋放,而C++拋出異常之前必須插入代碼來釋放相關資源,也可以通過auto_ptr(這個玩意兒本身就有一定的侷限性)來自動釋放內存資源。

三【C++異常類使用】

一般情況下,異常類的使用需要回答這三個問題:什麼時候拋出異常?拋什麼樣的異常?這個異常需要如何被處理?

對於第一個問題,我們需要理解異常是個什麼東西?異常一般是用來報告錯誤的一種機制。額,可是仔細推敲一下,那麼錯誤又是什麼東西呢?錯誤就是當被調用的函數無法履行開發者預先賦予它的職責時,我們就說該函數出錯了。這個時候就可以拋出異常來告訴上層的調用者出錯了。接下來,我們就需要考慮應該如何設計這個異常,這也就是第二個問題。


異常的設計需要根據具體的情況。如果異常處理相對複雜,可以將異常類的粒度設計的小一些,調用者可以根據不同的異常類型進行不同的處理,注意,這時異常類的抽象層次要與業務的抽象層次相對應。相反,如果異常處理沒那麼複雜,則粒度設計的大一些,使得一種異常處理方法可以應付多種異常情況。


一般情況下,我們有兩種處理方式:1放棄;2不放棄(貌似說了句廢話)。

當我們選擇放棄這個出錯函數的職責時,該異常就會繼續往上拋出,從而系統就會繼續棧展開(unwinding stack),直到被系統進入一個正常狀態(被捕獲),然後記錄日誌,準備處理下一個事件。這時,如果無法恢復到一個正常狀態時,最終則會導致進程終止。另外,當我們選擇嘗試着採取一些手段來解決這個錯誤的時候,我們可以根據具體的函數功能進行恢復。比如,當查詢某個數據庫出錯時,我們可以選擇重新查詢一次,或者選擇另一個備用數據庫進行查詢。


四【資源】

下面是一些關於異常討論的文章。

  1. 異常設計----何使用異常的原則
  2. 高效處理異常
  3. 異常處理之最佳實踐
  4. JAVA異常設計原則
  5. C++與Java異常處理的區別
  6. Thinking in C++ (中文版,英文版)壓縮包.zip


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章