C++函數異常說明

爲了能夠編寫適當的catch子句,瞭解一個函數是否拋出異常或會拋出哪些異常對函數的用戶來說是很有幫助的。

而我們可以通過 異常說明 進行對一個函數的異常進行說明, 如果函數拋出異常,被拋出的異常將是包含在該說明中的一種或是從列出的異常中派生的類型。

異常說明有如下的幾種形式:

1. 指定異常

T   funNname( parameterlist ) throw( T1, T2,····,Tn)

其中 T 是類型, parameterlist 是參數列表, 而類型 T1, T2,····,Tn 是函數會拋出的異常。


2. 不拋出異常

T   funNname( parameterlist ) throw( )

拋出異常類型列表爲空,表示的是該函數不拋出任何類型異常。


3. 拋出任意類型的異常

T   funNname( parameterlist );

這表示該函數可以拋出任意類型的異常。


下面通過一段簡單的代碼來說明異常說明的特別之處

  1. #include <iostream>  
  2. class demo  
  3. {  
  4. };  
  5. using namespace std;  
  6.    
  7. double divd(int a, int b) throw(int)  //異常說明,表示函數divd會拋出類型爲int的異常  
  8. {  
  9.     if(b == 0)  throw demo();         //拋出類型爲demo的異常  
  10.        
  11.     return    a/b;  
  12. }  
  13. int main()  
  14. {  
  15.     try  
  16.     {  
  17.         divd(1,0);  
  18.     }  
  19.     catch(demo)                       //捕獲異常類型demo  
  20.     {  
  21.         cout << " divided by zero " << endl;  
  22.     }  
  23.     catch(int)                        //捕獲異常類型int  
  24.     {  
  25.         cout<<"zero"<<endl;  
  26.     }  
  27.       
  28.     return 0;  
  29. }  
這段代碼的運行結果是輸出:  divided by zero

奇怪了,在 divd 函數的聲明中,只說明瞭拋出類型爲 int 的異常,爲什麼其函數內拋出的異常類型卻爲demo呢? 

我們可以暫時理解爲:在某函數的異常說明中的列出的類型與該函數內拋出的異常類型不完全匹配時, 但在異常處理代碼中的catch有對其類型的捕獲, 所以程序運行正常。

好,下面我們根據異常說明進行一些修改

  1. double divd(int a, int b) throw( )     //將throw(int) 改爲 throw( )  
修改之後,編譯運行,看到的輸出結果還是:   divided by zero

根據上面對異常說明的三種形式介紹,我們知道在函數聲明後面添加 throw()的意思是說明了此函數不會拋出任何的異常。那爲什麼這裏拋出了而且又被捕獲呢?

其實,在編譯的時候,編譯器不能也不會試圖驗證異常說明。因不能在編譯時檢查異常說明,異常說明的應用通常是有限的!

修改後的 divd 函數內繼續編寫有拋出異常的代碼, 編譯後再次運行程序,其輸出結果也表示異常機制執行正常。
其原因就如上述所說的理解那樣:編譯器不會對異常說明進行檢測,異常說明更多的是寫給函數的用戶看,讓它知道如何去捕獲這個函數可能拋出的異常類型,僅給用戶作參考。
而在一開始函數異常說明的類型與實際拋出的異常類型不匹配的情況中,同樣由於 “編譯器不會對異常說明進行檢測” 的原因,所以編譯通過,異常機制運行正常。

總結:異常說明還是有用的!但更多是寫給函數用戶看的。讓函數用戶清楚知道拋出的異常類型,從而更好和正確地在運用此函數時,編寫對其的異常檢測。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章