變成入門的時候可能經常遇到的錯誤:
this application has requested the runtime to terminate it in an unusual way. Please contact the application's support team for more information這是由於程序在運行時發生了未知的錯誤,例如:打開不存在的文件,爆棧,除數為0等錯誤,程序直接調用abort()函數直接終止程序的運行;當然,顯示的信息不一定就是上面這一條
上面這個情況是程序自己解決異常的問題,這種方式實際上是非常粗暴的,直接終止了程序運行,而且你還不知道程序錯在哪個位置,是因為什麼錯(當然,用萬能的cout強行追蹤也是闊以滴,哈哈)
所幸,c++引入了比較優雅的try... catch....異常機制來讓程序猿自己處理可能出現的異常,這種機制實際上是避免了程序直接調用abort()函數,使程序看起來更優雅一點,具體結構如下:
try{ // 可能會引發異常的代碼塊 }catch(exception argument){ //處理捕捉到的異常 }try...catch...機制實際上主要是以下幾個部分:
1.將可能引發異常的代碼(如:文件讀取等)放入try塊中
2.判斷在什麼時候拋出異常,也就是可能引發異常的代碼塊中需要添加異常拋出的語句,拋出異常通常使用 throw關鍵字
3.catch首先通過異常參數列表匹配產生的異常,如果匹配成功,那麼執行catch塊的代碼
先寫一個簡單的例子
首先是沒有異常處理的
#include隨便測試了一下,結果如下:using namespace std; int division(int a, int b){ return a / b; } int main(){ int a, b; while(1){ cout << Please input a and b: ; cin >> a >> b; cout << a / b = << division(a, b) << endl; } return 0; }
可以看到程序是直接結束了,並沒有理會那個while(1)
那我們現在來加一下異常
#include運行結果:using namespace std; int division(int a, int b){ if(b == 0) throw Divisor is not allowed to be 0; return a / b; } int main(){ int a, b; while(1){ cout << Please input a and b: ; cin >> a >> b; try{ cout << a / b = << division(a, b) << endl; cout << successful division << endl; }catch(const char* msg){ cout << Error message is: << msg << endl; } } return 0; }
可以看到現在我們可以知道是哪個地方除了問題,並且可以print出異常信息,更重要的是,程序依然可以繼續往下執行
可以看到,在產生異常之後,程序馬上跳轉到匹配的catch塊執行,而終止try塊中代碼的執行
當然,如果沒有匹配上產生的異常(上面這個例子只是簡單的匹配字符串,實際上更常用的是異常對象匹配),那麼程序同樣會調用abort()函數,然後編譯器給你提示一堆錯誤的信息時候,你的程序就掛掉了
看了上面這個例子,是不是感覺try和catch有一點實參和型參的感覺
那下面我們來看一個例子
我們現在吧異常當作一個MyException的對象來處理:
#include運行結果如下:using namespace std; class MyException{ public: MyException(){ msg = ; cout << in the default constructor << endl; } MyException(MyException &aa){ msg = aa.msg; cout << in the copy constructor << endl; } MyException(string msg_){ msg = msg_; cout << in the string constructor << endl; } string what(){ return msg; } string msg; }; int division(int a, int b){ if(b == 0){ MyException me(Divisor is not allowed to be 0); throw me; } return a / b; } int main(){ int a, b; while(1){ cout << Please input a and b: ; cin >> a >> b; try{ cout << a / b = << division(a, b) << endl; cout << successful division << endl; }catch(MyException &ME){ cout << Error message is: << ME.what() << endl; } } return 0; }
這裡大家可能會疑惑,因為在正常的函數參數傳遞中,我們傳遞引用就是為了避免重復地構造對象,但是在try...catch...中就不一樣了,throw在拋出異常的時候,無論catch是接受引用傳遞還是接受值傳遞,編譯器都會在throw異常時新建一個臨時對象,所以才會有上面結果中顯示的兩次構造MyException對象,而catch中的引用不過是指向這個臨時對象而不是原本的那個MyException對象,一搬都是吧拋出異常跟新建異常對象合並在一起,這樣更簡潔,所以上面拋出異常可以寫成
throw MyException(Divisor is not allowed to be 0);本來還想說一下exception和他的一些派生類的,不過好像網上挺多這些東西的,也沒什麼可講的,就收工了吧