異常
1、異常的概述
常見的異常:除0溢出,數組下標越界,所要讀取的文件不存在,空指針,內存不足等等。
c++的異常一旦拋出 如果不捕獲 該異常 程序直接退出
1.1、C語言通過返回值 來判斷 第一:容易忽略 第二:容易和正常的結果混淆
int myDiv(int a,int b)
{
if(b == 0)
return -1;//-1表示失敗
return a/b;
}
void test01()
{
int ret = myDiv(10,-10);
if(ret == -1)
{
cout<<"程序異常了"<<endl;
}
else
{
cout<<"程序正常"<<endl;
}
}
運行結果:
1.2、c++拋出異常 並捕獲
c++的異常一旦拋出 如果不捕獲 該異常 程序直接退出
拋出異常:throw
捕獲異常:try…catch
int myDiv01(int a,int b)
{
if(b==0)
throw 0;//拋出異常
return a/b;
}
void test02()
{
try{
int ret = myDiv01(10,0);
cout<<"ret = "<<ret<<endl;
}
#if 1
catch(int e)//只捕獲 拋出是int類型的異常
{
cout<<"捕獲到int類型異常 e = "<<e<<endl;
}
#endif
catch(float e)//只捕獲 拋出是float類型的異常
{
cout<<"捕獲到float類型異常 e = "<<e<<endl;
}
catch(char e)//只捕獲 拋出是char類型的異常
{
cout<<"捕獲到char類型異常 e = "<<e<<endl;
}
#if 0
catch(...)
{
cout<<"捕獲到其他異常"<<endl;
}
#endif
cout<<"程序做其他事情"<<endl;
}
運行結果:
2、棧解旋(unwinding)
異常被拋出後,從進入try塊起,到異常被拋擲前,這期間在棧上構造的所有對象,都會被自動析構。析構的順序與構造的順序相反,這一過程稱爲棧的解旋(unwinding).
void test03()
{
try{
Person ob1("00_德瑪");
Person ob2("01_小炮");
Person ob3("02_小法");
Person ob4("03_提莫");
throw 10;
}
catch(int)
{
cout<<"捕獲到int異常"<<endl;
}
cout<<"其他工作"<<endl;
}
運行結果:
3、異常的接口聲明
throw(int,char,char*) 只拋出int、char、char *異常
void testFunc01()
{
//函數內部可以拋出任何異常
//throw 10;
//throw 4.3f;
//throw 'a';
//throw "hehe";
string ob="heihie";
throw ob;
}
//只能拋出int char 異常
void testFunc02() throw(int,char)
{
throw 3.14f;
}
//函數 不拋出任何異常
void testFunc03()throw()
{
throw 10;//外部捕獲 不到
}
void test04()
{
try{
testFunc03();
}
catch(int e)//只捕獲 拋出是int類型的異常
{
cout<<"捕獲到int類型異常 e = "<<e<<endl;
}
catch(float e)//只捕獲 拋出是float類型的異常
{
cout<<"捕獲到float類型異常 e = "<<e<<endl;
}
catch(char e)//只捕獲 拋出是char類型的異常
{
cout<<"捕獲到char類型異常 e = "<<e<<endl;
}
catch(char const *e)//只捕獲 拋出是char *類型的異常
{
cout<<"捕獲到char const *類型異常 e = "<<e<<endl;
}
catch(string e)
{
cout<<"捕獲到string類型異常 e = "<<e<<endl;
}
}
4、異常的生命週期 的三種情況
4.1、以普通變量形式捕獲
class MyException
{
public:
MyException()
{
cout << "異常變量構造" << endl;
};
MyException(const MyException & e)
{
cout << "拷貝構造" << endl;
}
~MyException()
{
cout << "異常變量析構" << endl;
}
};
void text() //拋出異常
{
MyException ob;
throw ob;
}
void test01()
{
try {
text();
} catch (MyException e) {
cout << "捕獲到MyException異常" <<endl;
}
}
運行結果:
4.2、以指針形式捕獲
void test02()
{
try {
//text();
throw new MyException;
} catch (MyException *e) {
cout << "捕獲到MyException *異常" <<endl;
delete e; //必須記得釋放e
}
}
運行結果:
4.3、以引用形式捕獲(推薦使用)
void test03()
{
try {
//text();
throw MyException();
} catch (MyException &e) {
cout << "捕獲到MyException &異常" <<endl;
}
}
5、標準異常
案例
class Person2
{
private:
int age;
public:
Person2(int age)
{
if(age<0 || age >150)
throw out_of_range("age無效");
this->age =age;
}
};
void test06()
{
try{
Person2 ob(200);
}
catch(exception &e)
{
cout<<"捕獲到異常"<<e.what()<<endl;
//e.what() : age無效
}
}