1.棧展開過程沿著巢狀函式的呼叫鏈不斷查詢,直到找到了與異常匹配的catch句子為止,或者也可能一直沒找到匹配的catch,則程式將呼叫terminate,退出主函式後查詢過程終止。假設找到了乙個catch,則執行其中的**,執行完之後,找到與try塊關聯的最後乙個catch子句之後的點,並從這裡繼續執行。
2.如果在棧展開過程中推出了某個塊,編譯器將負責確保在這個塊中建立的物件能被正確銷毀,如果異常發生在建構函式中,即使某個物件只構造了一部分,我們也要確保已構造的成員能被正確地銷毀。
3.在棧展開的過程中,執行類型別的區域性物件的析構函式。因為這些析構函式是自動執行的,所以它們不應該丟擲異常,如果要丟擲異常,則應該在析構函式內部得到處理。一旦在棧展開的過程中析構函式丟擲了異常,並且析構函式自身沒能捕獲到該異常,則程式將被終止。
4.異常物件是一種特殊物件,編譯器使用異常丟擲表示式來對異常物件進行拷貝初始化。因此throw語句中的表示式必須擁有完全型別。而且如果該表示式是類型別的話,則相應的類必須含有乙個可訪問的析構函式和乙個可訪問的拷貝或移動建構函式。如果是陣列型別或函式型別,則表示式將被轉換成與之對應的指標型別。
5.異常物件位於編譯器管理的空間中,編譯器確保無論最終呼叫的是哪個catch子句都能訪問該空間。當異常處理完畢後,異常物件被銷毀。
6.當我們丟擲一條表示式時,該表示式的靜態編譯時型別決定了異常物件的型別。如果throw解引用乙個指向派生類的基類指標,則丟擲的物件將被切掉派生類的部分。
7.宣告的型別決定了處理**所能捕獲的異常型別,這個型別必須是完全型別,它可以是左值引用,但不能是右值引用。
8.通常情況下,如果catch接受的異常與某個繼承體系有關,則最好將該catch的引數定義成引用型別。
9.在搜尋catch語句的過程中,挑選出來的應該是第乙個與異常匹配的catch語句,因此,越是專門的catch越應該置於整個catch列表前端。
10.異常宣告中絕大多數型別轉換都不被允許,除了以下幾點情況:
11.有時候乙個單獨的catch語句不能完整地處理某個異常,可以通過重新丟擲的操作將異常傳遞給另外乙個catch語句,這裡的重新丟擲仍然是一條throw,只不過不包含任何表示式,空throw語句只能出現在catch語句或catch語句直接或間接呼叫的函式之內。如果在其他地方使用,編譯器將呼叫terminate。很多時候,catch語句會改變其引數的內容,只有當異常宣告是引用型別時,重新丟擲的引數才會保留改變的內容繼續傳播。
struct12.為了一次性捕獲所有的異常型別,我們使用省略號作為異常宣告,如果catch(...)與其他幾個catch語句一起出現,則catch(...)必須在最後的位置,出現在捕獲所有異常語句後面的catch語句將永遠不會被匹配。test
;struct testex : public
test
;testex t;
void
dotest()
catch (testex &e)
}int
main()
catch
(test e)
//注意,到這裡我們的全域性變數t沒有任何變化,如果想要t被改變,我們應該throw t的指標,即throw &t;
return0;
}
13.建構函式體內的catch語句無法處理建構函式初始值列表丟擲的異常。我們可以將建構函式寫成函式try語句塊的形式,這樣既能處理建構函式體,也能處理建構函式的初始化過程。但是注意,在初始化建構函式的引數時也可能發生異常,這樣的異常不屬於函式try語句塊的一部分,所以無法處理。
14.在c++11新標準中,我們可以通過提供noexcept說明指定某個函式不會丟擲異常。緊跟在函式的引數列表後面,要跟在const及引用限定符之後,在final,override或虛函式的=0之前。
15.編譯器並不會在編譯時檢查noexcept說明,如果乙個函式在說明了noexcept的同時又含有throw語句或者呼叫了可能丟擲異常的其他函式,編譯器將順利編譯過。一旦乙個noexcept函式丟擲了異常,程式就會呼叫terminate以確保遵守不在執行時丟擲異常的承諾,上述過程對是否執行棧展開未作約定,因此noexcept可以用在兩種情況之下:
16.noexcept說明符的實參常常與noexcept運算子混合使用,它是乙個一元運算子,返回值是乙個bool型別的右值常量表示式,用於表示給定的表示式是否會丟擲異常。和sizeof類似,noexcept也不會求其運算物件的值。
void test() noexcept(true); //17.如果我們為某個指標做了不丟擲異常的宣告,則該指標將只能指向不丟擲異常的函式。如果乙個虛函式承諾了它不會丟擲異常,則後續派生出來的虛函式也必須做出同意的承諾。不會丟擲異常
void
test1()
void test2() noexcept(test1); //
test1呼叫的所有函式都做了不丟擲說明並且test1本身不含有throw語句時,表示式為true
void test() noexcept(true); //18.標準庫異常類的繼承體系如下,我們可以直接使用也可以繼承它們定義自己的異常型別。不會丟擲異常
void test1() noexcept(false); //
可能會丟擲異常
void(*pf)(void) noexcept = test; //
正確void(*pf1)(void) noexcept = test1; //
錯誤class
base;};
class sub : public
base
//錯誤};
《C Primer》筆記之異常處理
一 丟擲異常 當程式發生異常的時候可以用throw語句丟擲異常物件,丟擲的異常物件由throw以後的實際物件所決定。假設有這樣乙個異常類繼承層次結構 基類是excep並從他派生出乙個mathexc異常物件,當宣告了乙個excep指標pe,則語句throw pe將丟擲乙個excep異常物件,無論pe實...
c primer異常處理 1
異常就是程式執行時出現的不正常,例如執行時耗盡了記憶體或遇到意外的非法輸入.異常存在於程式的正常功能之外,並要求程式立即處理.異常機制提供程式中錯誤檢測與錯誤處理部分之間的通訊.c 的異常處理中包括 throw表示式 錯誤檢測部分使用這種表示式來說明遇到了不可處理的錯誤.可以說,throw引發了異常...
29 C Primer 4th 筆記,異常處理
1 類成員的指標不同於指向普通資料或函式的指標,普通指標只根據物件或函式的型別而變化,而成員的指標必須反映成員所屬的類。2 異常是通過丟擲物件而引發的。該物件的型別決定應該啟用哪個處理 被選中的處理 是呼叫鏈中與該物件型別匹配且離丟擲異常位置最近的那個。異常以類似於將實參傳遞給函式的方式丟擲和捕獲。...