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