概念
異常事件(如:除 0 溢出,數組下標越界,所要讀取的文件不存在 , 空指針,內存不足
等等)
在 C 語言對錯誤的處理是兩種方法:
????????一是使用整型的返回值標識錯誤;
????????二是使用 errno 宏(可以簡單的理解為一個全局整型變量)去記錄錯誤。
C++ 異常不可忽略 ( 如果忽略,進程結束 ) 。
異常作為一個類,可以擁有自己的成員,這些成員就可以傳遞足夠的信息。
拋出異常 ----> 捕獲異常。
示例:
int main(int argc, char *argv[])
{int num = 10 / 0;cout << "OVER" << endl;return 0;
}
//不會顯示OVER,程序異常結束
拋出異常
語法:throw 值或變量;
例如:
????????throw 0;
????????throw 1.1;
????????throw 'a';
????????throw "abc";
捕獲異常
語法:
try{
????????可能會產生異常的代碼
????????111
????????222 出現異常
????????333
}
catch( 數據類型 1 變量名 )
{
????????當throw 的值與數據類型 1 相同進入此處
}
catch( 數據類型 2 變量名 )
{
????????當throw 的值與數據類型 2 相同進入此處
}
...
catch(...)
{
????????當throw 的值以上數據類型都不相同進入此處
}
示例
#include <iostream>
#include <cstring>
using namespace std;
//異常步驟,拋出異常,捕獲異常
int mydiv(int a,int b)
{if(b == 0){// 拋出異常int num = 0;throw num;}return a / b;
}
void test01(){try{mydiv(10,0);}catch(int e){cout << e << endl;}catch(char const* s){cout << s << endl;}catch(...){cout << "其他異常" << endl;}
}
int main(int argc, char *argv[])
{test01();return 0;
}
棧解旋
概念
????????異常被拋出后,從進入 try 塊起 , 到異常被拋擲前 , 這期間在棧上構造的所有對象 , 都會
被自動析構。析構的順序與構造的順序相反 , 這一過程稱為棧的解旋
示例
class A{
private:
int num;
public:
A(int num):num(num)
{cout << "構造函數" << num << endl;
}
~A()
{cout << "析構函數" << num << endl;
}
};
void test02()
{A a1(1);A a2(2);throw 0;
}
int main(int argc, char *argv[])
{try{test02();}catch(...){}return 0;
}
結果
???????? 構造函數1
? ? ? ? 構造函數2
???????? 析構函數2
???????? 析構函數1
異常的接口聲明
作用
????????限定異常拋出的類型種類
語法
????????返回值類型 函數名( 形參列表 )throw( 數據類型 1, 數據類型 2,...)
????????{
????????????????函數體
????????}
????????注意:
????????????????聲明異常后,當前函數中只能拋出指定類型的異常
????????????????throw():不允許拋出任何異常
示例
void fun01()throw(int,char)
{// throw 10;//可以// throw 'a';//可以// throw 3.14f;//不可以
}
void test03(){try{fun01();}catch(int){cout << "int的異常" << endl;}catch(char){cout << "char的異常" << endl;}catch(float){cout << "float的異常" << endl;}
}
int main(int argc, char *argv[])
{test03();return 0;
}
異常對象的生命周期
示例1:拋出異常對象
#include <iostream>
#include <cstring>
using namespace std;
class B{
private:int num;
public:B(int num):num(num){cout << "構造函數" << num << endl;}B(const B& b){this->num = b.num;cout << "拷貝構造" << num << endl;}~B(){cout << "析構函數" << num << endl;}
};
void fun02()
{throw B(10);
}
void test04()
{try{fun02();}catch(B b){}
}
int main(int argc, char *argv[])
{test04();cout << "OVER" << endl;return 0;
}
結果
示例2:拋出異常對象指針
#include <iostream>
#include <cstring>
using namespace std;
class B{
private:int num;
public:B(int num):num(num){cout << "構造函數" << num << endl;}B(const B& b){this->num = b.num;cout << "拷貝構造" << num << endl;}~B(){cout << "析構函數" << num << endl;}
};
void fun02()
{throw new B(10);
}
void test04()
{try{fun02();}catch(B *b){}
}
int main(int argc, char *argv[])
{test04();cout << "OVER" << endl;return 0;
}
結果:
示例3:拋出異常對象引用
#include <iostream>
#include <cstring>
using namespace std;
class B{
private:int num;
public:B(int num):num(num){cout << "構造函數" << num << endl;}B(const B& b){this->num = b.num;cout << "拷貝構造" << num << endl;}~B(){cout << "析構函數" << num << endl;}
};
void fun02()
{throw B(10);
}
void test04()
{try{fun02();}catch(B &b){}
}
int main(int argc, char *argv[])
{test04();cout << "OVER" << endl;return 0;
}
結果:
異常的多態
概念 :?? 子類異常對象可以被父類異常類型捕獲
示例1:
class BaseException{};
class MyException01:public BaseException{};
class MyException02:public BaseException{};
void test05()
{try{throw MyException01();}catch(BaseException){cout << "可以捕獲子類異常" << endl;}
}
int main(int argc, char *argv[])
{test05();return 0;
}
示例 2: 子類異常重寫父類虛函數
class BaseException{
public:virtual void printMsg(){}
};
class NullException:public BaseException{
public:virtual void printMsg(){cout << "空指針異常" << endl;}
};
class ArrOutException:public BaseException{
public:virtual void printMsg(){cout << "數組下標越界異常" << endl;}
};
void test05()
{try{throw NullException();}catch(BaseException &e){e.printMsg();}
}
int main(int argc, char *argv[])
{test05();return 0;
}
標準異常庫
簡介
標準庫中也提供了很多的異常類,它們是通過類繼承組織起來的。異常類繼承層級 . 結構圖
所示

標準異常使用
void test06()
{try{throw bad_alloc();}catch(exception &e){cout << e.what() << endl;}
}
int main(int argc, char *argv[])
{test06();return 0;
}
自定義異常
步驟
????????1,定義一個類
????????2,繼承與異常類
????????3,重寫 wait 方法
示例
class my_exception:public exception
{
private:char* msg;
public:my_exception(){}my_exception(char* msg){this->msg = msg;}const char *what()const noexcept{return msg;}
};
void test07()
{try{throw my_exception("自定義異常");}catch(exception &e){cout << e.what() << endl;}
}
int main(int argc, char *argv[])
{test07();return 0;
}