網(wǎng)站首頁 編程語言 正文
在 C 語言中,如果發(fā)生錯誤,上級函數(shù)要進行出錯處理,層層上傳,容易造成過多的出錯處理代碼,并且傳遞的效率比較低下。
C++ 中的異常
C++ 中,異常的引發(fā)和異常的處理不必處于同一個函數(shù)中,因此底層函數(shù)可以著重于解決具體問題,而不必過多的考慮異常處理
異常是專門針對抽象編程中的一系列錯誤處理的,遇到錯誤信息就轉(zhuǎn)到若干級之上進行重新嘗試
異常脫離于函數(shù)機制,決定了其對函數(shù)的跨越式回跳
語法
try
{
? ? statement;
}
catch(ExceptionType var)
{
? ? statement;
}
被檢測的語句放在 try 塊中
try catch 語句中的花括號是語法的一部分,不能省略
try-catch 結(jié)構(gòu)中,只能有一個 try 塊,catch 塊可以有多個,以便與不同的類型信息匹配,有點類似于 switch-case 結(jié)構(gòu)
利用 throw 拋出的異常類型,可以傳遞系統(tǒng)預(yù)定義的標(biāo)準(zhǔn)類型或自定義類型
從 throw 拋出異常,到 catch 捕獲異常,有點類似與利用函數(shù)的返回值進行復(fù)制一樣,因此如果使用了自定義類型,需要考慮自定義類型的賦值和拷貝問題
如果 catch 語句沒有與之相匹配的異常類型信息,可以用(...)表示可以捕獲任何異常類型的信息,有點類似與 switch-case 結(jié)構(gòu)中的 default
try-catch 結(jié)構(gòu)可以與 throw 在同一函數(shù)中,也可以不在同一個函數(shù)中,throw 拋出異常后,會先在本函數(shù)中尋找與之相匹配的 catch 塊,如果沒有與之相匹配的 catch,就可以轉(zhuǎn)到上一層 try-catch,如果仍然沒有
匹配到,則轉(zhuǎn)到再上一層 try-catch...,如果最終到不到與之匹配的 try-catch 塊,系統(tǒng)就會調(diào)用系統(tǒng)函數(shù),terminal 使程序終止
#include <iostream>
?
using namespace std;
?
void func1()
{
? ? double a;
? ? try{
? ? ? ? throw a;
? ? }catch(double)
? ? {
? ? ? ? cout<<"catch func1()"<<endl; //throw
? ? }
? ? cout<<"end func1()"<<endl;
? ? return ;
}
?
void func2()
{
? ? try{
? ? ? ? func1();
? ? }catch(int)
? ? {
? ? ? ? cout<<"catch func2()"<<endl;
? ? }
? ? cout<<"end func2()"<<endl;
}
?
void func3()
{
? ? try{
? ? ? ? func2();
? ? }catch(char)
? ? {
? ? ? ? cout<<"catch func3()"<<endl;
? ? }
? ? cout<<"end func3()"<<endl;
}
?
int main()
{
? ? try{
? ? ? ? func3();
? ? }catch(double)
? ? {
? ? ? ? cout<<"catch main"<<endl;
? ? }
? ? cout<<"end main"<<endl;
? ? return 0;
}
結(jié)果為:
catch func1()
end func1()
end func2()
end func3()
end main
上邊的異常傳遞路線為 func3->func2()->func1(),在 func1 中找到對應(yīng)的 catch 塊,然后執(zhí)行對應(yīng) catch 塊中的語句,輸出:
catch func1()
整個的異常處理已經(jīng)結(jié)束,跳出 func1() 的 try-catch 塊,繼續(xù)執(zhí)行 func1() 的函數(shù)體,陸續(xù)輸出:
end func1()
end func2()
end func3()
end main
此時進程結(jié)束。
如果將 func1() 中的 catch 到的異常類型換個類型,如:
catch(void *)
結(jié)果為:
catch main
end main
則會在 func1(),func2(),func3() 中都找不到對應(yīng)的 catch 匹配,直到 main 函數(shù)才能找到對應(yīng)的匹配,然后輸出:
catch main
end main
如果將 main 函數(shù)中的 catch 捕獲類型也修改為:
catch(void *)
結(jié)果為:
terminate called after throwing an instance of 'double'
?
This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.
此時系統(tǒng)就會調(diào)用系統(tǒng)函數(shù),使程序終止。
拋出類型聲明
為了增強程序的可讀性,可以在函數(shù)聲明時就列出所有可能拋出的異常類型
void func() throw (A,B,C); ? ? // 表明該函數(shù)只會拋出 A,B,C 及其子類型的異常
如果在函數(shù)聲明時沒有聲明可能拋出的異常類型,則函數(shù)可以拋出任意類型的異常
不拋出任何類型異常的函數(shù),可以聲明為:
void func() throw();
如果一個函數(shù)拋出了拋出類型聲明中所不允許的異常,unexpected 函數(shù)被調(diào)用,啟用 terminal 函數(shù)中止程序
棧自旋
異常被拋出后,從進入 try 塊起,到異常被拋擲前,這期間在棧上的構(gòu)造的所有對象,都會被自動析構(gòu)
析構(gòu)的順序與構(gòu)造的順序相反。這一過程稱為棧的解旋
而堆上的空間,則會泄漏
#include <iostream>
?
using namespace std;
?
class A
{
public:
? ? A(){ cout<<"A()"<<endl; }
? ? ~A(){ cout<<"~A()"<<endl; }
};
?
int func1()
{
? ? A a;
? ? if(1)
? ? ? ? throw('a');
? ? return 0;
}
?
int func2()
{
? ? A b;
? ? func1();
? ? return 1;
}
?
int main()
{
? ? try{
? ? ? ? func2();
? ? }catch(int x){
? ? ? ? cout<<"x"<<endl;
? ? }catch(double y){
? ? ? ? cout<<"y"<<endl;
? ? }catch(...){
? ? ? ? cout<<"no x, no y"<<endl;
? ? }
? ? return 0;
}
結(jié)果為:
A()
A()
~A()
~A()
no x, no y
如果 throw 的是一個類對象:
#include <iostream>
?
using namespace std;
?
class A
{
public:
? ? A(){ cout<<"A()"<<endl; }
? ? A(const A &obj){ cout<<"A(const A &obj)"<<endl; }
? ? ~A(){ cout<<"~A()"<<endl; }
};
?
int func1()
{
? ? A a;
? ? if(1)
? ? ? ? throw(a);
? ? return 0;
}
?
int func2()
{
? ? func1();
? ? return 1;
}
?
int main()
{
? ? try{
? ? ? ? func2();
? ? }catch(int x){
? ? ? ? cout<<"x"<<endl;
? ? }catch(double y){
? ? ? ? cout<<"y"<<endl;
? ? }catch(const A &a){
? ? ? ? cout<<"no x, no y"<<endl;
? ? }
? ? return 0;
}
結(jié)果為:
A()
A(const A &obj)
~A()
no x, no y
~A()
原文鏈接:https://blog.csdn.net/SAKURASANN/article/details/105983755
相關(guān)推薦
- 2022-01-13 使用postcss插件配置rem和手寫rem的方法
- 2022-12-08 Apache?Cordova?Android原理應(yīng)用實例詳解_Android
- 2022-09-26 Ajax異步請求的五個步驟及實戰(zhàn)案例_AJAX相關(guān)
- 2022-11-30 Android?Binder?通信原理圖文詳解_Android
- 2022-10-24 Python?NumPy教程之?dāng)?shù)據(jù)類型對象詳解_python
- 2022-07-19 react props的特點
- 2022-06-19 C語言詳細(xì)分析宏定義的使用_C 語言
- 2022-02-07 SSH連服務(wù)器提示“Permission denied,please try again”的原因與解
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡單動態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支