c++中的異常處理 try ,將可能發生異常的代碼塊括起來; catch,處理異常代碼塊; throw,拋出異常對象。 一般情況下,try與catch二者是不可分割的。 例如:
從上面代碼中,我們可以看到在try中,throw后面的代碼是不執行的,所以平時就會忽略這個問題,從而導致代碼出現bug,這個也是筆試時經常出現的一類問題。
接下來就用這個例子簡單的看一下。> try { int *p = new int; ofstream outf("data.txt");//資源的開辟 cin>>a>>b>>c; if(a<=0||b<=0||c<=0) { throw "input is invalid!"; // 拋出異常,即拋出常量字符串 } delete p; outf.close();//資源的刪除}catch(const char *errstr)//專門處理異常代碼塊 { cout<<errstr<<endl; delete p; outf.close(); }我們在try函數中,進行了資源的開辟與釋放,一旦我們的輸入有問題,我們的throw函數將會截斷try函數,使其不會繼續進行下去,這樣會造成內存泄漏問題。所以我們必須在每個catch里面進行資源的釋放。(c++11版本或許會有Finally函數進行統一釋放。)
template<typename T,int SIZE>class CArray{public: CArray() { cout<<this<<endl; cout<<"CArray()"<<endl; mCur = 0; } ~CArray() { cout<<this<<endl; cout<<"~CArry()"<<endl; } void push_back(const T &val) { if(mCur >= SIZE) { throw "array is false"; } mArr[mCur++] = val; } void pop_back() { mCur--; } T& Operator[](int index) { return mArr[index]; }PRivate: T mArr[SIZE]; int mCur;};void func1(){ CArray<int,5> arr1; try { for(int i=0;i<6;++i) { arr1.push_back(rand()%100+1); } } catch(const char* err) { cerr<<err<<endl; //cerr對應標準錯誤流,用于顯示錯誤消息。默認情況下被關聯到標準輸出流,但它不被緩沖. }}int main(){ func1(); return 0;}經過上面的代碼,關于異常處理我們可以得出下面倆點: 1、異常處理后,拋到相應的catch塊處理,處理完以后,程序仍然可以繼續執行。 2、拋出異常,不僅僅是拋出常量字符串,更有各種類型。
我們可以在下面尋找類型相同的catch塊; 首先在當前函數下尋找類型相同的; 若沒有找到匹配的catch塊,則把問題拋給上方(上方即是調用這個函數 的一個函數,這里指的是func1()函數) 若一直拋到main函數里面,還沒有,則系統返回。throw CExcepFull<T>("array is full",val);CExcepFull<T> tmp = CExcepFull<T>("array is full",val);throw tmp;throw函數首先構造一個臨時的異常對象,存儲在異常存儲區域. 在拋出對象時,編譯器會拷貝構造一個新的對象,然后拋出新對象,臨時對象析構。 開始執行catch塊,當catch函數的右括號一出,則新對象的生命周期消失(即異常存儲區域的異常對象)。
我們通常在寫代碼時,可能會有疏忽,并不能全部確定異常情況,這時,我們就可以用到這個語句:catch(...) //catch all{}這個函數可以保證程序不會掛掉,如果沒有相同類型,最終會匹配到這里,由于,這個函數與不同類型的函數都可以進行匹配,又因為函數匹配是從上倒下進行的,所以此函數必須寫在末尾。
異常的重新拋出
在深層次函數的調用中,出現了多種異常,同時又解決了多種異常, 對于main函數來說并不知情,現在main函數想檢測一下,在整個函數中在運行過程中,拋出異常的個數。我們可以用rethrow語句,
catch(const CExcepFull<int> &err) { err.show(); throw; }表示將異常拋出到調用方(func1),在調用方加上一個try,catch語句,加上一個計數器,即可以解決此問題。 異常的規范: 異常的規范是在c++99里面是不支持的,但在此c++11是支持的。
void push_back(const T &val) throw();//該接口不拋異常,否則掛掉 ,throw()是函數首部的一部分,是不能缺少的void push_back(const T &val) throw(int);//只拋出整形異常,其他掛掉新聞熱點
疑難解答
圖片精選