要點(diǎn)
- 異常根據(jù)拋出的類型捕獲,可以直接捕獲接收或通過引用接收觉阅。但二者同時只能存在一個囱淋。
- 棧內(nèi)存創(chuàng)建的對象指針拋出后會產(chǎn)生野指針問題
- 動態(tài)創(chuàng)建對象的指針拋出后可以正常捕獲使用,但是需要手動釋放病袄。
- 函數(shù)聲明可以加上異常聲明。限制函數(shù)可以拋出的異常類型赘阀。
- 異常有棧解鎖機(jī)制益缠,棧內(nèi)存中創(chuàng)建的對象在異常拋出后會自動析構(gòu)。
- 異郴可以捕獲并繼續(xù)向上拋出幅慌。
示例代碼
#include "stdafx.h"
#include "iostream"
#include "string.h"
using namespace std;
#pragma warning(disable : 4996)
class ExceptionA {
private:
char *msg;
public:
ExceptionA(const char *msg) {
cout << "構(gòu)造" <<msg<< endl;
if (msg == NULL) {
this->msg = NULL;
}else{
this->msg = new char[strlen(msg) + 1];
strcpy(this->msg, msg);
}
}
char * getMsg()const {
return this->msg;
}
ExceptionA(const ExceptionA& e) {
cout << "拷貝構(gòu)造" << endl;
if (this->msg == NULL) {
delete[]this->msg;
}
this->msg = new char[strlen(e.getMsg()) + 1];
strcpy(this->msg, e.getMsg());
}
~ExceptionA() {
cout << "析構(gòu)" << msg << endl;
if (this->msg != NULL) {
delete[]this->msg;
}
}
};
void funcA(int x) {
switch (x)
{
case 0:{
//throw異常后,temp1會自動析構(gòu)轰豆,而temp不會自動析構(gòu)和釋放
ExceptionA *temp = new ExceptionA("temp");
ExceptionA temp1("temp1");
throw 1;
}
break;
case 1:
throw 'a';
break;
case 2:
//可以直接接受或使用引用接收胰伍。推薦使用引用接收
throw(ExceptionA("msg 2"));
break;
case 3:
//拋出指針,但對象會被清理酸休。catch到的指針是野指針
throw(&ExceptionA("msg 3"));
break;
case 4: {
//拋出動態(tài)分配的指針骂租。catch到后使用完后需要delete
ExceptionA* e = new ExceptionA("msg4");
throw(e);
}
break;
case 5:
throw 3.14f;
case 6:
throw 3.14;
}
cout << "funcA success " << x << endl;
}
void funcB(int index) throw(float ,double){
try {
funcA(index);
}
catch (int e) {
cout << "catch int " << e << endl;
}
catch (char e) {
cout << "catch char " << e << endl;
}
catch (ExceptionA e) {
cout << "catch ExceptionA " << e.getMsg() << endl;
}
//使用對象接收和使用對象的引用接收不能同時存在。
//catch (ExceptionA &e) {
// cout << "catch ExceptionA & " << e.getMsg() << endl;
//}
catch (ExceptionA *e) {
cout << "catch ExceptionA * " << e->getMsg() << endl;
delete e;
}
catch (float e) {
//接續(xù)向上拋出異常
cout << "catch float and throw " << e << endl;
throw e;
}
catch (double e) {
//接續(xù)向上拋出異常雨席,但函數(shù)的方法上有限制可以拋出異常的類型菩咨。這里會出錯
cout << "catch double and throw " << e << endl;
throw e;
}
}
int main()
{
try {
funcB(6);
}
catch (float e) {
cout << "main catch " << e << endl;
}
return 0;
}
異常處理場景演示
-
funcB(0)
0.png
這里創(chuàng)建了兩個對象一個在堆中動態(tài)創(chuàng)建temp.一個在棧中temp1。執(zhí)行結(jié)果看到temp1自動被析構(gòu)陡厘,而temp未被析構(gòu)抽米。c++在異常拋出后有棧解鎖機(jī)制,會自動析構(gòu)在棧中創(chuàng)建的對象糙置。
-
funcB(1)
1.png
這里就是按類型在funcA中正常的catch
-
funcB(2) 棧內(nèi)存對象
-
用對象直接接收
2.png
這里看到當(dāng)拋出對象時候云茸,catch中接受時類似方法實(shí)參到形參的傳遞,進(jìn)行拷貝構(gòu)造谤饭。
-
用對象的引用接收
7.png
catch中得到對象的引用标捺。
-
-
funcB(3) 拋出棧內(nèi)存對象的指針
3
catch得到對象的指針前。對象已被析構(gòu)揉抵,這里得到的就是野指針亡容。
-
funcB(4) 動態(tài)創(chuàng)建對象
4.png
可以正常catch到并使用。但使用完后需要手動釋放冤今。
-
funcB(5) 捕獲到異常后繼續(xù)向上拋出
5.png
funcA中繼續(xù)拋出闺兢,在main中正常捕獲。
-
funcB(6) 方法異常類型聲明
6.png
限制方法能夠拋出異常的類型戏罢,如果不在范圍內(nèi)屋谭,運(yùn)行會報錯