C++中處理異常的過程是這樣的:在執行程式發生異常,可以不在本函數中處理,而是拋出一個錯誤資訊,把它傳遞給上一級的函數來解決,上一級解決不了,再傳給其上一級,由其上一級處理。如此逐級上傳,直到最高一級還無法處理的話,運行系統會自動調用系統函數terminate,
學會使用terminate函數有助於異常處理
一 當一個異常產生的時候調用terminate函數,代碼:
[cpp] view plaincopyprint?#include <iostream> #include <exception> using namespace std; void on_terminate(){ cout<<"terninate function called!"<<endl; cin.get(); } int main(void){ set_terminate(on_terminate); throw exception(); cout<<"terminate function not called!"<<endl; cin.get(); return 0; }
terminate被調用的情況:
1 當發送一個異常,並且建構函式產生異常
2 當發送一個異常,或者解構函式產生異常
3 一個靜態對象的構造或者析構發送一個異常
4 以atexit註冊的函數發生異常的時候
5 自訂一個異常,但是實際上沒有異常產生的時候
6 調用預設的unexcepted()函數時候
例子說話:
[cpp] view plaincopyprint?#include <iostream> #include <exception> using namespace std; void on_terminate(){ cout<<"terminate function called!"<<endl; cin.get(); } class custom_exception{ custom_exception(){ } custom_exception(const custom_exception& excep){ throw exception(); } }; void case_1(){ try{ throw custom_exception(); } catch(...){ } }
當一個函數拋出了一個throw異常的時候,如果該函數內部構造了對象的話,系統會先對該對象調用解構函式,當對象調用完了解構函式以後,才開始執行異常的拋出工作。
同時在具有繼承關係的類的異常中,子類的異常應該放在前面,而基類的異常應該放到最後面,這樣可以使子類的異常先獲得處理,父類的異常最後處理。
[cpp] view plaincopyprint?#include<iostream> using namespace std; class X { public: class Trouble {}; //注意:類中嵌套類的申明和定義,學習!!! class small: public Trouble {}; class big:public Trouble {};//類中的繼承!!! void f(){ throw big(); } }; int main() { X x; try{ x.f(); } catch(X::Trouble &) { cout<<"caught Trouble"<<endl; } catch(X::small&) { cout<<"caught small"<<endl; } catch(X::big&) { cout<<"caught big"<<endl; } return 0; }
如果這樣的話,拋出的big()類型異常則被trouble類壟斷,應該倒著寫才可以實現順序捕獲所有異常,另外使用...可以捕捉所有的異常,這個應該放到最後面才可以。
省略符號異常處理器不允許接受任何參數,所以無法得到任何相關異常的資訊,也無法知道異常的類型,這種catch語句經常用於清理資源並重新拋出所捕獲的異常。