錯誤處理技術
1.終止程式(段錯誤)
2.返回錯誤碼
3.返回合法值
4.調用一個預先設定的出現錯誤時調的函數(回呼函數)
異常處理
-當一個函數發現自己無法處理的錯誤時拋出異常,讓函數的調用者直接或間接的處理這個問題。
異常的拋出和捕獲
- 異常是通過拋出對象而引發的,對象的類型決定了應該啟用哪個處理代碼。
- 處理代碼是與該物件類型匹配且離拋出異常位置最近的哪個
- 拋出異常後會釋放局部儲存物件,所處被拋出的對象葉歡給作業系統了,throw會初始化一個拋出特殊的異常對象副本(匿名對象),異常對象由編譯管理,對象傳給對應的catch處理後撤銷。 棧展開
- 拋出異常的時候,暫停當前函數的執行,開始尋找對應的匹配catch。
- 首先在throw本身是否在團員塊內部,如果是尋找catch,如果有匹配的,就處理;如果沒有匹配的,則退出當前函數棧,繼續在調用函數的棧中尋找;如果到main函數的棧依舊沒有找到匹配的,就終止程式。 異常捕獲的匹配規則
-異常物件類型與catch的類型必須完全符合
例外:
1.從非const對象到const對象。
2.從衍生類別型到基類類型的轉換。
3.數群組轉換為指向數組的指標,函數轉換為指向函數的指標。
#include <iostream>#include <string>using namespace std;class Exception{public : Exception(int errId, const char * errMsg) : _errId(errId ) , _errMsg(errMsg ) {} void What () const { cout<<"errId:" <<_errId<< endl; cout<<"errMsg:" <<_errMsg<< endl; }private : int _errId ; // 錯誤碼 string _errMsg ; // 錯誤訊息};void Func1 (bool isThrow){ // ... if (isThrow ) { throw Exception (1, "拋出 Excepton對象" ); } // ... printf("Func1(%d)\n" , isThrow);}void Func2 (bool isThrowString, bool isThrowInt){ // ... if (isThrowString ) { throw string ("拋出 string對象" ); } // ... if(isThrowInt ) { throw 7; } printf("Func2(%d, %d)\n" , isThrowString, isThrowInt );}void Func (){ try { Func1(false ); Func2(true , true); } catch(const string& errMsg) { cout<<"Catch string Object:" <<errMsg<< endl; } catch(int errId) { cout<<"Catch int Object:" <<errId<< endl; } catch(const Exception& e) { e.What (); } catch(...) { cout<<" 未知異常"<< endl; } printf ("Func()\n");}int main(){ Func(); return 0;}
運行結果如下: 異常的重新拋出
有可能單個catch不能完全處理一個異常,在進行一些校正處理後,希望再交給更外層的調用鏈函數來處理,catch則可以通過重新將異常傳遞給上層的函數來進行處理。
#include <iostream>#include <string>using namespace std;class Exception{public : Exception(int errId = 0, const char * errMsg = "" ) : _errId(errId ) , _errMsg(errMsg ) {} void What () const { cout<<"errId:" <<_errId<< endl; cout<<"errMsg:" <<_errMsg<< endl; }private : int _errId ; // 錯誤碼 string _errMsg ; // 錯誤訊息};void Func1 (){ throw string ("Throw Func1 string");}void Func2 (){ try { Func1(); } catch(string & errMsg) { cout<<errMsg <<endl; Exception e (1, "Rethorw Exception"); throw e ; // throw; // throw errMsg; }}void Func3 (){ try { Func2(); } catch (Exception & e) { e.What (); }}int main(){ Func3(); return 0;}
運行結果如下:
異常 建構函式&解構函式
建構函式完成對象的構造和初始化,要保證不在建構函式中拋出異常,否則可能導致對象不完整或沒有完全初始化 解構函式 主要完成資源的清理,保證不在解構函式中拋出異常,否則導致資源泄漏(記憶體流失,控制代碼未關閉等)。