《C Primer》筆記之異常處理

2021-04-22 23:14:07 字數 4278 閱讀 3549

一、丟擲異常

當程式發生異常的時候可以用throw語句丟擲異常物件,丟擲的異常物件由throw以後的實際物件所決定。假設有這樣乙個異常類繼承層次結構:基類是excep並從他派生出乙個mathexc異常物件,當宣告了乙個excep指標pe,則語句throw *pe將丟擲乙個excep異常物件,無論pe實際指向的物件是excep或是mathexc型別。

丟擲異常的過程可以這樣描述:1.建立乙個臨時的異常物件;2.將這個臨時的異常複製到異常儲存區;3.呼叫析構函式銷毀掉先前建立的臨時物件;3.丟擲異常儲存區中的異常物件。這個丟擲過程意味著即使將乙個已經定義的全域性的異常類物件用在throw語句中,實際被丟擲的異常物件只是這個全域性物件的乙個拷貝,在catch語句中對這個異常物件的任何操作都不會引起全域性物件的改變。

二、try塊

使用try塊告訴程式這個**塊可能會丟擲異常。try塊將形成乙個區域性域。try塊可以包括乙個函式定義中的某些**段,也可以包括整個函式定義。當try塊包括整個函式定義時只要將try放在函式的參數列之後(類的const成員函式則放在const之後)。如:int main() try

當try塊被用在類的建構函式中時,並且想要捕獲類物件構造期間丟擲的異常則try應該放在建構函式參數列和成員初始化列表之間。如:istack::istack(int size) try :_size(size)

三、捕獲異常

可以使用catch語句來捕獲異常,catch語句中的引數就像函式的參數列一樣。在捕獲異常時catch語句根據其出現的先後次序嘗試進行匹配,如果乙個catch語句被匹配則之後的catch語句都將不再被考慮。這和函式的過載解析有所區別,函式的過載解析將考慮所有在呼叫點可見的函式宣告並找出乙個最佳可行函式;而catch語句僅僅是按照先後持續進行匹配,匹配後即使後續的catch語句有比當前catch語句更匹配的語句也不被考慮。

在嘗試catch語句匹配時不允許除派生類到基類物件或派生類指標、引用到基類指標、引用以外的一切轉換。因此一切將繼承層次物件作為catch語句的引數時,所有派生類物件的catch語句都應該放在繼承類catch語句之前。

如果catch語句的引數是乙個類物件那麼應該將他宣告為引用或指標,這是因為:1.避免不必要的類複製和析構以提高效率;2.操作throw丟擲的異常物件,以便重新丟擲以後後續catch語句的處理;3.如果catch的引數是基類的引用或指標,當丟擲的異常物件是派生類時,那麼就能根據實際的異常物件來呼叫相關的虛函式。

四、異常規範

使用一層規範時我們必須注意以下兩點1.函式指標的異常規範必須比賦給他的函式的異常規範寬鬆或者相同;2.派生類虛函式的異常規範必須與基類虛函式的異常規範相同或者更加嚴格。

五、棧展開

當丟擲乙個異常時,程式**將首先在丟擲異常的函式中查詢能夠處理該異常的catch語句,如果該函式定義中找不到能夠處理該異常的catch語句或者該函式不在try塊中時,程式**將沿著函式呼叫鏈向上查詢相應的catch語句。在這個過程中從異常丟擲的函式到能夠處理異常的catch語句所在的函式之間的函式都會被結束,所有的自動物件、類物件都會被釋放,但是由於自由儲存區上的物件不會被自動釋放由此可能帶來記憶體的洩漏,解決這個問題的方法有兩種:1.用類來封裝資源的分配和釋放就象auto_ptr模板一樣;2.在相應的函式中包含相應的catch語句用於釋放資源,之後重新丟擲異常。

c++異常處理

2023年03月14日 星期三 23:15

1.         異常處理的使用

首先說明,千萬別對異常處理鑽牛角尖,那樣會死人的(當然是煩死的)!

在c++程式設計處理中,我秉承這樣乙個思想,就是:能不用異常處理的就不用。因為造成的混亂實在是太——多了。如果能用其他方法捕捉到錯誤並處理的話,誓死不用異常處理!呵呵,或許有點偏激,但我認為,這不失為乙個避免不必要的錯誤的乙個好辦法。當什麼分配記憶體失敗,開啟檔案失敗之類的通常錯誤,我們只需用assert,abort之類的函式就解決問題了。也就是說,假如有足夠的資訊去處理乙個錯誤,那麼這個錯誤就不是異常。

當然了,異常處理的存在也有它本身的意義和作用。不是你說不用就不用的,有些地方還非得用不可!

比如說,在當前上下文環境中,無法捕捉或確定的錯誤型別,我們就得用乙個異常丟擲到更大的上下文環境當中去。還有,異常處理的使用呢,可以使出錯處理程式與「通常」**分離開來,使**更簡潔更靈活。另外就是程式必不可少的健壯性了,異常處理往往在其中扮演著重要的角色。

ok,下面闡述一下。

2.         丟擲異常

關——鍵字(周星馳的語氣):throw

例——句:throw exceptionclass(「oh, ****! it』s a exception!l 「);

例句中,exceptionclass是乙個類,它的建構函式以乙個字串做為引數,用來說明異常。也就是說,在throw的時候,c++的編譯器先構造乙個exceptionclass的物件,讓它作為throw的返回值,拋——出去。同時,程式返回,呼叫析構。看下面這個程式:

#include

class exceptionclass

~exceptionclass()       

void mythrow()       

};void main()        catch(...)    

}大家看看結果就知道了,throw後,呼叫當前類的析構,整個結束了這個類的歷史使命。唉~~

3.         異常規格說明

如果我們呼叫別人的函式,裡面有異常丟擲,我用去檢視它的源**去看看都有什麼異常丟擲嗎?可以,但是太——煩躁。比較好的解決辦法,是編寫帶有異常丟擲的函式時,採用異常規格說明,使我們看到函式宣告就知道有哪些異常出現。

異常規格說明大體上為以下格式:

void exceptionfunction(argument…) throw(exceptionclass1, exceptionclass2, ….)

對了,所有異常類都在函式末尾的throw()的括號中得以說明了,這樣,對於函式呼叫者來說,是一清二楚了!

注意下面一種形式:

void exceptionfunction(argument…) throw()

表明沒有任何異常丟擲。

而正常的void exceptionfunction(argument…)則表示:可能丟擲任何一種異常,當然就,也可能沒有異常,意義是最廣泛的哦。

4.         構造和析構中的異常丟擲

55555,到了應該注意的地方了。

先看個程式,假如我在建構函式的地方丟擲異常,這個類的析構會被呼叫嗎?可如果不呼叫,那類裡的東西豈不是不能被釋放了??

程式:#include

#include

class exceptionclass1

~exceptionclass1()

};void main()catch(...){}}

結果為:

exceptionclass1()

throw a exception

沒了,沒了,到此為止了!可是,可是,在這兩句輸出之間,我們已經給s分配了記憶體,**去了?記憶體釋放了嗎?沒有,沒有,因為它是在析構函式中釋放的,哇!問題大了去了。怎麼辦?怎麼辦?

為了避免這種情況,應避免物件通過本身的建構函式涉及到異常丟擲。即:既不在建構函式中出現異常丟擲,也不應在構造函式呼叫的一切東西中出現異常丟擲。否則,只有完蛋。

那麼,在析構函式中的情況呢?我們已經知道,異常丟擲之後,就要呼叫本身的析構函式,如果這析構函式中還有異常丟擲的話,則已存在的異常尚未**獲,會導致異常捕捉不到哩。

完,也就是說,我們不要在建構函式和析構函式中存在異常丟擲。

5.         異常捕獲

上邊的程式不知道大家看懂了沒,異常捕獲已經在上面出現了也。

沒錯,就是trycatch(…)這樣的結構!

try後面的花括號中,就是有可能涉及到異常的各種宣告啊呼叫啊之類的,如果有異常丟擲,就會被異常處理器截獲捕捉到,轉給catch處理。先把異常的類和catch後面小括號中的類進行比較,如果一致,就轉到後面的花括號中進行處理。

例如丟擲異常是這麼寫的:

void f()

假設類exceptionclass有個成員函式function()在有異常時進行處理或相應的訊息顯示(只是做個例子哦,別挑我的刺兒)。

那麼,我可以這麼捕捉: trycatch(exceptionclass e);

當然,象在上面程式中出現的一樣,我可以在catch後用三個點來代表所有異常。如trycatch(…){}。這樣就截斷了所有出現的異常。有助於把所有沒出現處理的異常遮蔽掉(我是這麼認為的j)。

異常捕獲之後,我可以再次丟擲,就用乙個不帶任何引數的throw語句就可以了,例如:try(f())catch(…)

C Primer 筆記 異常處理

1.棧展開過程沿著巢狀函式的呼叫鏈不斷查詢,直到找到了與異常匹配的catch句子為止,或者也可能一直沒找到匹配的catch,則程式將呼叫terminate,退出主函式後查詢過程終止。假設找到了乙個catch,則執行其中的 執行完之後,找到與try塊關聯的最後乙個catch子句之後的點,並從這裡繼續執...

c primer異常處理 1

異常就是程式執行時出現的不正常,例如執行時耗盡了記憶體或遇到意外的非法輸入.異常存在於程式的正常功能之外,並要求程式立即處理.異常機制提供程式中錯誤檢測與錯誤處理部分之間的通訊.c 的異常處理中包括 throw表示式 錯誤檢測部分使用這種表示式來說明遇到了不可處理的錯誤.可以說,throw引發了異常...

29 C Primer 4th 筆記,異常處理

1 類成員的指標不同於指向普通資料或函式的指標,普通指標只根據物件或函式的型別而變化,而成員的指標必須反映成員所屬的類。2 異常是通過丟擲物件而引發的。該物件的型別決定應該啟用哪個處理 被選中的處理 是呼叫鏈中與該物件型別匹配且離丟擲異常位置最近的那個。異常以類似於將實參傳遞給函式的方式丟擲和捕獲。...