您好,登錄后才能下訂單哦!
異常,當(dāng)一個函數(shù)發(fā)現(xiàn)一個無法處理的錯誤時拋出異常,讓函數(shù)的
調(diào)用者直接或間接的處理這個問題。
異常處理,是一種允許兩個獨立開發(fā)的程序組件在程序執(zhí)行期間遇到程序不正常的
情況(稱為異常,exception )時相互通信的機(jī)制。
異常拋出:
throw (表達(dá)式)
異常發(fā)現(xiàn)與拋出異常:
/*發(fā)現(xiàn)異常并且拋出異常*/ try { //可能出現(xiàn)異常的語句 }
捕獲異常:
catch(類型名 + 形參名) //捕獲特定類型異常 { }
catch(...) //捕獲任意類型異常(在不確定異常類型時使用) { }
下來看一個簡單的例子:
#include<iostream> using namespace std; int Div(int a, int b) { return a/b; } int main() { Div(1,0); system("pause"); return 0; }
結(jié)果顯示:
程序直接崩潰,由于調(diào)用時傳入第二個參數(shù)是零,零不能作除數(shù),所以會崩潰,下面使用異常處理這個問題:
#include <iostream> #include <string> using namespace std; int Div(int a, int b) { if(b == 0) { throw string("parameter error.");//異常拋出 } return a/b; } int main() { try { Div(1, 0);//發(fā)現(xiàn)異常,與拋出異常 } catch(const string& S) { cout<<S<<endl;//捕獲異常 } system("pause"); return 0; }
程序可以正常運行,也可以看到異常出現(xiàn)的地方,這樣就可以很清楚的解決這個問題。
下面再看個了例子:
#include <iostream> #include <string> using namespace std; void test() { int* p = new int(1); if(1) { throw string("error."); } delete p; } int main() { try { test(); } catch(const string& S) { cout<<S<<endl; } system("pause"); return 0; }
結(jié)果顯示:
這個程序運行貌似沒有問題,其實問題大了。
void test() { int* p = new int(1); if(1) { throw string("error."); //程序執(zhí)行到這里,直接就去catch()那塊了, //導(dǎo)致new出來的內(nèi)存沒有釋放,造成內(nèi)存泄漏。 } delete p; }
內(nèi)存泄漏:
會導(dǎo)致你開辟出來的那塊內(nèi)存以后就不可以用了,這樣多泄漏幾次,你的電腦就哈哈了,會很卡,很卡。
內(nèi)存泄漏危害:
從用戶使用程序的角度來看,內(nèi)存泄漏本身不會產(chǎn)生什么危害,作為一般的用戶,根本感覺不到內(nèi)存泄漏的存在。真正有危害的是內(nèi)存泄漏的堆積,這會最終消耗盡系統(tǒng)所有的內(nèi)存。從這個角度來說,一次性內(nèi)存泄漏并沒有什么危害,因為它不會堆積,而隱式內(nèi)存泄漏危害性則非常大,因為較之于常發(fā)性和偶發(fā)性內(nèi)存泄漏它更難被檢測到。
當(dāng)然,這里并不是說內(nèi)存泄漏,下面可以用異常來處理上面這個問題:
#include <iostream> #include <string> using namespace std; void test() { int* p = new int(1); try//發(fā)現(xiàn)異常 { if(1) { throw string("error.");//異常拋出 } } catch(...)//捕獲異常 { delete p;//釋放開辟的空間 throw;//異常重新拋出 } delete p; } int main() { try//發(fā)現(xiàn)重新拋出的異常 { test(); } catch(const string& S)//捕獲異常 { cout<<S<<endl; } system("pause"); return 0; }
結(jié)果顯示:
這樣就不會出現(xiàn)內(nèi)存泄漏,也會很清楚的在控制臺顯示錯誤的信息。
異常重新拋出:在異常處理過程中也可能存在單個catch 子句不能完全處理異常的情況。在某些修
正動作之后,catch 子句可能決定該異常必須由函數(shù)調(diào)用鏈中更上級的函數(shù)來處理那么catch子句可以通過重新拋出(rethrow )該異常把異常傳遞給函數(shù)調(diào)用鏈中更上級的另一個catch子句,rethrow 表達(dá)式的形式為:
throw;
rethrow 表達(dá)式重新拋出該異常對象rethrow 只能出現(xiàn)在catch 子句的復(fù)合語句中。被重新拋出的對象就是其原來的異常對象。
棧展開:
在查找用來處理被拋出異常的catch 子句時因為異常而退出復(fù)合語句和函數(shù)定義這個過程
拋出異常的時候,將暫停當(dāng)前函數(shù)的執(zhí)行,開始查找對應(yīng)的匹配catch語句。首先檢查throw本身是否在catch塊內(nèi)部,如果是,再查找匹配的catch語句。如果有匹配的,則處理。沒有則退出當(dāng)前函數(shù)棧,繼續(xù)在調(diào)用函數(shù)的棧中進(jìn)行查找。不斷重復(fù)上述過程。若到達(dá)main函數(shù)的棧,依舊沒有匹配的,則終止程序。
上述這個沿著調(diào)用鏈查找匹配的catch語句的過程稱為棧展開。找到匹配的catch語句并處理以后,會繼續(xù)沿著catch語句后繼繼續(xù)執(zhí)行。
異常捕獲的匹配規(guī)則:
異常對象的類型與catch說明符的類型必須完全匹配。
只有以下幾種情況例外:
1. 允許從非const對象到const的轉(zhuǎn)換。
2. 允許從派生類型到基類類型的轉(zhuǎn)換。
3. 將數(shù)組轉(zhuǎn)換為指向數(shù)組類型的指針,將函數(shù)轉(zhuǎn)換為指向函數(shù)類型的指針。
異常處理總結(jié):
異常處理就是通過throw,try,catch,這三個關(guān)鍵字,來發(fā)現(xiàn)異常,并拋出異常,捕獲異常,可以做出相應(yīng)的處理。(這只是簡單的異常處理)
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。