異常:存在於運行時的反常行爲,這些行爲超過了函數的正常的功能範圍。ios
異常處理:處理程序中的錯誤,異常處理機制爲程序中異常檢測和異常處理這兩部分的協做提供支持。c++
在C++中,異常處理包括:ide
#include<iostream> using namespace std; //異常基本語法 int divide(int x ,int y){ if (y == 0){ throw y; //拋異常 } return x / y; } void test01(){ //試着去捕獲異常 try{ divide(10, 0); } catch (int e){ //異常時根據類型進行匹配 cout << "除數爲" << e << "!" << endl; } } void CallDivide(int x,int y){ divide(x, y); } //a() -> b() - >c() -> d(),d()中的異常一層層向上拋到terminate的標準庫函數,直處處理爲止 void test02(){ try{ CallDivide(10,0); } catch (int e){ cout << "除數爲" << e << endl; } } //C++異常機制跨函數 //異常必須處理,若是異常拋到頂層尚未處理,程序便會掛掉。 int main(){ //test01(); test02(); }
異常被拋出後,從進入try塊起,到異常被拋前,這期間在棧上構造的全部對象,都會被自動析構,析構的順序與構造的順序相反,這一過程即爲棧解旋。函數
構造函數沒有返回類型,沒法經過返回值來報告運行狀態,因此經過異常機制來解決構造函數的出錯問題。this
#define _CRT_SECURE_NO_WARNINGS #include <iostream> using namespace std; class Person{ public: Person(){ cout << "對象構建!" << endl; } ~Person(){ cout << "對象析構!" << endl; } }; int divide(int x,int y){ Person p1, p2; if (y == 0){ throw y; } return x / y; } void test01(){ try{ divide(10,0);//棧解旋 } catch (int e){ cout << "異常捕獲!" << endl; } } int main(void) { test01(); return 0; } /* 結果: 對象構建! 對象構建! 對象析構! 對象析構! 異常捕獲! */
#define _CRT_SECURE_NO_WARNINGS #include <iostream> using namespace std; //這個函數只能拋出int float char三種類型異常,拋出其餘的就報錯 void func() throw(int,float,char){ throw "abc"; } //不能拋出任何異常 void func02() throw(){ throw -1; } //能夠拋出任何類型異常 void func03(){ } int main(void) { try{ func(); } catch (char* str){ cout << str << endl; } catch (int e){ cout << "異常!" << endl; } catch (...){ //捕獲全部異常 cout << "未知類型異常!" << endl; } return 0; } //結果: 未知類型異常!
throw的異常是有類型的,能夠是數字、字符串、類對象,catch需嚴格匹配異常類型。spa
#define _CRT_SECURE_NO_WARNINGS #include <iostream> using namespace std; void func01(){ throw 1; //拋出int類型異常 } void func02(){ throw "exception"; } class MyException{ public: MyException(const char* str){ error = new char[strlen(str)+1]; strcpy(error, str); } MyException(const MyException& ex){ this->error = new char[strlen(ex.error) + 1]; strcpy(this->error,ex.error); } MyException& operator=(const MyException& ex){ if (this->error != NULL){ delete[] this->error; this->error = NULL; } this->error = new char[strlen(ex.error) + 1]; strcpy(this->error, ex.error); } void what(){ cout << error << endl; } ~MyException(){ if (error != NULL){ delete[] error; } } public: char* error; }; void fun03(){ throw MyException("我剛寫異常!"); } void test01(){ try{ func01(); } catch (int e){ cout << "int 異常捕獲!" << endl; } //---------------------------------- try{ func02(); } catch (const char* e){ cout << "const char* 異常捕獲!" << endl; } //---------------------------------- try{ fun03(); } catch (MyException e){ e.what(); } } int main(void){ test01(); return 0; } /* int 異常捕獲! const char* 異常捕獲! 我剛寫異常! */
#define _CRT_SECURE_NO_WARNINGS #include <iostream> using namespace std; class MyException { public: MyException() { cout << "構造函數!" << endl; } MyException(const MyException& ex) { cout << "拷貝構造!" << endl; } ~MyException() { cout << "析構函數!" << endl; } }; void func() { //throw &(MyException()); //建立匿名對象,調用構造 //throw new MyException();//用指針接 throw MyException(); } void test01(); int main(void) { test01(); return 0; } /* void test01();{ try { func(); } catch (MyException e) { cout << "異常捕獲!" << endl; } } 普通類型去接,結果爲: 構造函數! 拷貝構造! 異常捕獲! 析構函數! 析構函數! */ /* void test01();{ try { func(); } catch (MyException& e) { cout << "異常捕獲!" << endl; } } 引用去接,結果爲: 構造函數! 異常捕獲! 析構函數! */ /* void test01();{ try { func(); } catch (MyException* e) { cout << "異常捕獲!" << endl; detele e; } } 指針去接,結果爲: 構造函數! 異常捕獲! 析構函數! */