C++中異常處理的文法 try catch throw
來源:互聯網
上載者:User
C++中異常處理的文法。
關鍵字
1、 try
2、 catch
3、 throw
其中關鍵字try表示定義一個受到監控、受到保護的程式碼塊;關鍵字catch與try遙相呼應,定義當try block(受監控的程式塊)出現異常時,錯誤處理的程式模組,並且每個catch block都帶一個參數(類似於函數定義時的數那樣),這個參數的資料類型用於異常對象的資料類型進行匹配;而throw則是檢測到一個異常錯誤發生後向外拋出一個例外狀況事件,通知對應的catch程式塊執行對應的錯誤處理。
文法
1、還是給一個例子吧!如下:
int main()
{
cout << "In main." << endl;
//定義一個try block,它是用一對花括弧{}所括起來的塊範圍的代碼塊
try
{
cout << "在 try block 中, 準備拋出一個異常." << endl;
//這裡拋出一個異常(其中異常對象的資料類型是int,值為1)
//由於在try block中的代碼是受到監控保護的,所以拋出異常後,程式的
//控制流程便轉到隨後的catch block中
throw 1;
cout << "在 try block 中, 由於前面拋出了一個異常,因此這裡的代碼是不會得以執行到的" << endl;
}
//這裡必須相對應地,至少定義一個catch block,同樣它也是用花括弧括起來的
catch( int& value )
{
cout << "在 catch block 中, 處理異常錯誤。異常對象value的值為:"<< value << endl;
}
cout << "Back in main. Execution resumes here." << endl;
return 0;
}
2、文法很簡單吧!的確如此。另外一個try block可以有多個對應的catch block,可為什麼要多個catch block呢?這是因為每個catch block匹配一種類型的異常錯誤對象的處理,多個catch block呢就可以針對不同的異常錯誤類型分別處理。畢竟異常錯誤也是分層級的呀!有致命的、有一般的、有警告的,甚至還有的只是事件通知。例子如下:
int main()
{
try
{
cout << "在 try block 中, 準備拋出一個int資料類型的異常." << endl;
throw 1;
cout << "在 try block 中, 準備拋出一個double資料類型的異常." << endl;
throw 0.5;
}
catch( int& value )
{
cout << "在 catch block 中, int資料類型處理異常錯誤。”<< endl;
}
catch( double& d_value )
{
cout << "在 catch block 中, double資料類型處理異常錯誤。”<< endl;
}
return 0;
}
3、一個函數中可以有多個trycatch結構塊,例子如下:
int main()
{
try
{
cout << "在 try block 中, 準備拋出一個int資料類型的異常." << endl;
throw 1;
}
catch( int& value )
{
cout << "在 catch block 中, int資料類型處理異常錯誤。”<< endl;
}
//這裡是二個trycatch結構塊,當然也可以有第三、第四個,甚至更多
try
{
cout << "在 try block 中, 準備拋出一個double資料類型的異常." << endl;
throw 0.5;
}
catch( double& d_value )
{
cout << "在 catch block 中, double資料類型處理異常錯誤。”<< endl;
}
return 0;
}
4、上面提到一個try block可以有多個對應的catch block,這樣便於不同的異常錯誤分類處理,其實這隻是異常錯誤分類處理的方法之一(暫且把它叫做橫向展開的吧!)。另外還有一種就是縱向的,也即是分層的、trycatch塊是可以嵌套的,當在低層的trycatch結構塊中不能匹配到相同類型的catch block時,它就會到上層的trycatch塊中去尋找匹配到正確的catch block異常處理模組。常式如下:
int main()
{
try
{
//這裡是嵌套的trycatch結構塊
try
{
cout << "在 try block 中, 準備拋出一個int資料類型的異常." << endl;
throw 1;
}
catch( int& value )
{
cout << "在 catch block 中, int資料類型處理異常錯誤。”<< endl;
}
cout << "在 try block 中, 準備拋出一個double資料類型的異常." << endl;
throw 0.5;
}
catch( double& d_value )
{
cout << "在 catch block 中, double資料類型處理異常錯誤。”<< endl;
}
return 0;
}
5、講到是trycatch塊是可以嵌套分層的,並且通過異常對象的資料類型來進行匹配,以找到正確的catch block異常錯誤處理代碼。這裡就不得不詳細敘述一下通過異常對象的資料類型來進行匹配找到正確的catch block的過程。
(1) 首先在拋出異常的trycatch塊中尋找catch block,按順序先是與第一個catch block塊匹配,如果拋出的異常對象的資料類型與catch block中傳入的異常對象的臨時變數(就是catch語句後面參數)的資料類型完全相同,或是它的子類型對象,則匹配成功,進入到catch block中執行;否則到二步;
(2) 如果有二個或更多的catch block,則繼續尋找匹配第二個、第三個,乃至最後一個catch block,如匹配成功,則進入到對應的catch block中執行;否則到三步;
(3) 返回到上一級的trycatch塊中,按規則繼續尋找對應的catch block。如果找到,進入到對應的catch block中執行;否則到四步;
(4) 再到上上級的trycatch塊中,如此不斷遞迴,直到匹配到頂級的trycatch塊中的最後一個catch block,如果找到,進入到對應的catch block中執行;否則程式將會執行terminate()退出。
另外分層嵌套的trycatch塊是可以跨越函數範圍的,常式如下:
void Func() throw()
{
//這裡實際上也是嵌套在裡層的trycatch結構塊
try
{
cout << "在 try block 中, 準備拋出一個int資料類型的異常." << endl;
//由於這個trycatch塊中不能找到匹配的catch block,所以
//它會繼續尋找到調用這個函數的上層函數的trycatch塊。
throw 1;
}
catch( float& value )
{
cout << "在 catch block 中, int資料類型處理異常錯誤。”<< endl;
}
}
int main()
{
try
{
Func();
cout << "在 try block 中, 準備拋出一個double資料類型的異常." << endl;
throw 0.5;
}
catch( double& d_value )
{
cout << "在 catch block 中, double資料類型處理異常錯誤。”<< endl;
}
catch( int& value )
{
//這個例子中,Func()函數中拋出的異常會在此被處理
cout << "在 catch block 中, int資料類型處理異常錯誤。”<< endl;
}
return 0;
}
6、剛才提到,嵌套的trycatch塊是可以跨越函數範圍的,其實這裡面還有另外一層涵義,就是拋出異常對象的函數中並不一定必須存在trycatch塊,它可以是調用這個函數的上層函數中存在trycatch塊,這樣這個函數的代碼也同樣是受保護、受監控的代碼;當然即便是上層調用函數不存在trycatch塊,也只是不能找到處理這類異常對象錯誤處理的catch block而已,常式如下:
void Func() throw()
{
//這裡實際上也是嵌套在裡層的trycatch結構塊
//由於這個函數中是沒有trycatch塊的,所以它會尋找到調用這個函數的上
//層函數的trycatch塊中。
throw 1;
}
int main()
{
try
{
//調用函數,注意這個函數裡面拋出一個異常對象
Func();
cout << "在 try block 中, 準備拋出一個double資料類型的異常." << endl;
throw 0.5;
}
catch( double& d_value )
{
cout << "在 catch block 中, double資料類型處理異常錯誤。”<< endl;
}
catch( int& value )
{
//這個例子中,Func()函數中拋出的異常會在此被處理
cout << "在 catch block 中, int資料類型處理異常錯誤。”<< endl;
}
//如果這裡調用這個函數,那麼由於main()已經是調用棧的頂層函數,因此不能找
//到對應的catch block,所以程式會執行terminate()退出。
Func();
// [特別提示]:在C++標準中規定,可以在程式任何地方throw一個異常對象,
// 並不要求一定只能是在受到try block監控保護的範圍中才能拋出異常,但
// 如果在程式中出現了拋出的找不到對應catch block的異常對象時,C++標
// 准中規定要求系統必須執行terminate()來終止程式。
// 因此這個常式是可以編譯通過的,但運行時卻會異常終止。這往往給軟體
// 系統帶來了不安全性。與此形成對比的是java中提供的異常處理模型卻是不
// 永許出現這樣的找不到對應catch block的異常對象,它在編譯時間就給出錯誤
// 提示,所以java中提供的異常處理模型往往比C++要更完善,後面的章節
// 會進一步對這兩種異常處理模型進行一個詳細的分析比較。
return 0;
}