簡記c、c++、java異常處理機制的區別
一、C異常處理:用於多層返回的setjmp/longjmp機制
C中的異常處理是通過setjmp.h標頭檔案中定義的巨集setjmp和巨集longjmp實現的。
類似於退棧,setjmp/longjmp機制的使用方法:
- 在希望進行錯誤處理的位置用setjmp巨集進行標註 把當前的“環境”(函式堆疊和暫存器)以陣列方式儲存
- 在可能出現錯誤的地方使用longjmp巨集進行控制轉移 恢復儲存的“環境”並將執行位置轉回setjmp語句的下一句
典型方法:
#include <iostream> #include <csetjmp> #include <cstdlib> using namespce std; static jmp_buf env; //jmp_buf型別的物件用於儲存“環境” void f( int ); int main() { /*setjmp()第一次被呼叫時返回0,若是longjmp()導致的控制返回,ret會被重置為longjmp()的第二個引數。 int ret = setjmp( env); if(1 == ret) { cout<<"這裡是異常處理"<<endl; exit(0); } f(0); return 0; } void f(int j) { for(;j<6;j++) { if(3==j) longjmp(env,1); } }
二、C++異常處理:try--catch--throw
雖然C++中也可以使用C的方法,但是這樣做會出很多問題,例如會跳過類解構函式的呼叫,並且setjmp()的開銷較大(儲存的資訊)
其實通過字面意思就差不多可以理解用法了:
- 將要檢查的語句放在try{}中
- 在try{}模組中加入throw,即要丟擲的異常
- 在try{}模組後加上catch{}模組捕捉異常
典型方法:
#include <iostream> #include <cstdlib> using namespce std; class MyException{}; void f(int)throw(MyException); // throw(MyException)是可選的;(比之於java),如果throw(),則表示不丟擲任何異常 int main() { try{ f(0); } catch(MyException &e){ // 引數列表裡可以只有型別,不包括物件(比之於java) cout<<"捕捉到異常"; } return 0; } void f(int j)throw(MyException) { throw MyException(); }
補充:
(1)try和catch塊中必須要用花括號括起來,即使花括號內只有一個語句也不能省略花括號;
(2)try和catch必須成對出現,一個try_catch結果中只能有一個try塊,但可以有多個catch塊,以便與不同的異常資訊匹配;
(3)如果在catch塊中沒有指定異常資訊的型別,而用刪節號"...",則表示它可以捕獲任何型別的異常資訊;
(4)如果throw不包括任何表示式,表示它把當前正在處理的異常資訊再次丟擲,傳給其上一層的catch來處理;
(5)C++中一旦丟擲一個異常,如果程式沒有任何的捕獲,那麼系統將會自動呼叫一個系統函式terminate,由它呼叫abort終止程式;
三、java異常處理:try--catch--throw--finally
與C++的異常處理語法相似,java的異常處理在“字面”上看,只比C++多了個finally,但是細節上還是有許多不同
用法:
典型方法:
- try{}模組 放入要檢查的語句
- 放入throw語句 要丟擲的異常
- catch{}模組 捕捉異常
- finally{}模組 無論是否丟擲異常,都要執行這一模組,無論如何,最後都要執行finally模組
class MyException extends Exception{}class Test{
static void f() throws MyException{} //注意此處throws MyException 為必須的(比之於C++),且,java用的throws,而C++是throw
public static void main( String[] args {
try{
f();
}
catch(MyException e){ //catch必須顯式的指出引數物件
system.out.println("捕捉到異常");
}
finally{
system.out.println("這裡是finally模組");
}
}
}補充:
java中還有unchecked異常機制,異常的型別為RuntimeException或Error的子類,此類異常可以不必在try--catch程式碼塊中丟擲,可以直接丟擲,且,其被系統捕獲導致程式終止
四、一些額外的c++與java的比較
- C++可以丟擲所有型別的物件,而java只能丟擲Throwable的子類
- java中若要丟擲異常必須在函式頭部宣告,而C++中只是推薦採用此方式
- java在catch模組中必須顯式的制定一個異常引數物件,而C++不是必須的
五、C與C++的堆疊解退比較
假設都是在main函式中遞迴呼叫函式f(int),f(3)會導致異常
此為C:
此為C++: