異常就是運行時出現出現的不正常(沒說一樣),例如系統運行時耗盡了內存或遇到意外的非法輸入。C++的異常處理中,需要由問題檢測部分拋出一個對象給處理代碼,通過這個對象的類型和內容,兩個部分能夠就出現了什麼錯誤進行通信。C++的異常處理機制包括:
throw表達式,錯誤檢測部分使用這種表達式來說明遇到了不可處理的錯誤,可以說throw引發(raise)了異常。
try塊(try block),錯誤處理使用它來處理異常。try語句以try關鍵字開始,並以一個或者多個catch子句結束。
由標準庫所定義的一組異常類,用來在throw和catch之間傳遞有關的錯誤信息。
一個最簡單的例子:
- #include <iostream>
- using namespace std;
- void f(int a);
- int main()
- {
- try
- {
- f(0);
- }
- catch(int a) //參數是有類型的
- {
- cout<<"handling exception "<<a<<endl;
- }
- return 0;
- }
- void f(int a)
- {
- if(a == 0)
- throw 0;
- else
- cout<<"fun() end"<<endl;
- }
有以下幾點需要注意的:
(1)可以拋出基本數據類型異常,如int和char等;
(2)可以拋出複雜數據類型異常,如結構體(在C++中結構體也是類)和類;
(3)在一個複雜的系統中一個try塊可能包含另一個tyr塊的函數,它的try塊又調用了含有try塊的另一個函數。拋出異常的時候,將暫停當前函數的執行,開始查找匹配的catch子句。首先檢查throw本身是否在try塊內部,如果是,檢查與該try相關的catch子句,看是否其中一是否與被拋出的對象匹配。如果找到匹配的catch,就處理異常;如果找不到,就退出當前函數(釋放當前函數的內存並撤銷局部對象),並繼續在調用函數中查找,如果找不到匹配的catch,調用函數也退出,並繼續在調用這個函數中查找。這個過程稱爲棧展開(stack
unwinding),沿嵌套函數調用鏈繼續向上,直至爲異常找到一個catch子句。
棧展開期間,提早退出包含throw的函數和調用鏈中可能的其他函數。因異常而退出函數時,編譯器保證適當地撤銷局部對象。每個函數退出的時候,它的局部存儲被釋放。但是如果一個塊直接分配資源,在釋放資源前發生異常,在棧展開期間不會釋放該資源,例如一個塊可以通過調用new動態分配內存,如果該塊因異常而退出,編譯器不會刪除該指針,已分配的內存將不會釋放。
析構函數應該從不拋出異常。(這時C++ Primary上的原話,應該,但還是有可能)在爲某個異常進行棧展開的時候,析構函數如果又拋出自己的未經處理的另外一個異常,將會導致調用標準庫terminate函數,一般而言terminate函數將調用abort函數,強制從整個程序非正常退出。實踐中,因爲析構函數釋放資源,所以它不太可能拋出異常。標準庫類型都保證它們的析構函數不會引發異常。
(4)不能不處理異常,異常是足夠重要、使程序不能繼續正常執行的事件。如果找不到匹配的catch,程序就調用庫函數terminate。
(5)在查找匹配的catch期間,找到的catch不必是與異常最匹配的那個catch,相反,將選中第一個找到的可以處理該異常的catch。因此,在catch中,最特殊的catch必須最先出現。異常與catch異常說明符匹配的規則比匹配實參和形參類型的規則更嚴格,大多數轉換都不允許除下面三種:
1.允許從非const到const的轉換
2.允許從派生類到基類類型的轉換(所以catch(exception)一般都可以捕捉到標準庫異常,exception爲其他異常類基類)
3.允許將數組轉換爲指向數組類型的指針
(6)有可能單個catch不能完全處理一個異常,在進行了一些校正行動之後,catch可能確定該異常必須由函數調用鏈中更上層的函數來處理,catch可以通過重新拋出(rethrow)將異常傳遞給函數調用鏈中更上層的函數,重新拋出是後面不跟類型或表達式的一個throw:
- throw;
空throw語句將重新拋出異常對象,它只能出現在catch或者從catch調用的函數中,如果在處理代碼不活動時候碰見空throw,就調用terminate函數。
(7)即使函數不能處理被拋出的異常,它可能想要在隨拋出異常退出之前執行一些動作,可以使用捕獲所有異常的catch子句,形式爲catch(...),catch(...)經常與重新拋出表達式結合使用,catch完成可作的所有局部工作,然後重新拋出異常:
- catch(...){
- //work to partially handle the exception
- throw;
- }
(8)下面是標準的exception類的層次(java裏面也有類似的)
參考:
C++ Primary
http://www.cnblogs.com/skyseraph/archive/2010/10/24/1859898.html
http://blog.csdn.net/tuwen/article/details/2295853