網站首頁 編程語言 正文
在 C 語言中,如果發生錯誤,上級函數要進行出錯處理,層層上傳,容易造成過多的出錯處理代碼,并且傳遞的效率比較低下。
C++ 中的異常
C++ 中,異常的引發和異常的處理不必處于同一個函數中,因此底層函數可以著重于解決具體問題,而不必過多的考慮異常處理
異常是專門針對抽象編程中的一系列錯誤處理的,遇到錯誤信息就轉到若干級之上進行重新嘗試
異常脫離于函數機制,決定了其對函數的跨越式回跳
語法
try
{
? ? statement;
}
catch(ExceptionType var)
{
? ? statement;
}
被檢測的語句放在 try 塊中
try catch 語句中的花括號是語法的一部分,不能省略
try-catch 結構中,只能有一個 try 塊,catch 塊可以有多個,以便與不同的類型信息匹配,有點類似于 switch-case 結構
利用 throw 拋出的異常類型,可以傳遞系統預定義的標準類型或自定義類型
從 throw 拋出異常,到 catch 捕獲異常,有點類似與利用函數的返回值進行復制一樣,因此如果使用了自定義類型,需要考慮自定義類型的賦值和拷貝問題
如果 catch 語句沒有與之相匹配的異常類型信息,可以用(...)表示可以捕獲任何異常類型的信息,有點類似與 switch-case 結構中的 default
try-catch 結構可以與 throw 在同一函數中,也可以不在同一個函數中,throw 拋出異常后,會先在本函數中尋找與之相匹配的 catch 塊,如果沒有與之相匹配的 catch,就可以轉到上一層 try-catch,如果仍然沒有
匹配到,則轉到再上一層 try-catch...,如果最終到不到與之匹配的 try-catch 塊,系統就會調用系統函數,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;
}
結果為:
catch func1()
end func1()
end func2()
end func3()
end main
上邊的異常傳遞路線為 func3->func2()->func1(),在 func1 中找到對應的 catch 塊,然后執行對應 catch 塊中的語句,輸出:
catch func1()
整個的異常處理已經結束,跳出 func1() 的 try-catch 塊,繼續執行 func1() 的函數體,陸續輸出:
end func1()
end func2()
end func3()
end main
此時進程結束。
如果將 func1() 中的 catch 到的異常類型換個類型,如:
catch(void *)
結果為:
catch main
end main
則會在 func1(),func2(),func3() 中都找不到對應的 catch 匹配,直到 main 函數才能找到對應的匹配,然后輸出:
catch main
end main
如果將 main 函數中的 catch 捕獲類型也修改為:
catch(void *)
結果為:
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.
此時系統就會調用系統函數,使程序終止。
拋出類型聲明
為了增強程序的可讀性,可以在函數聲明時就列出所有可能拋出的異常類型
void func() throw (A,B,C); ? ? // 表明該函數只會拋出 A,B,C 及其子類型的異常
如果在函數聲明時沒有聲明可能拋出的異常類型,則函數可以拋出任意類型的異常
不拋出任何類型異常的函數,可以聲明為:
void func() throw();
如果一個函數拋出了拋出類型聲明中所不允許的異常,unexpected 函數被調用,啟用 terminal 函數中止程序
棧自旋
異常被拋出后,從進入 try 塊起,到異常被拋擲前,這期間在棧上的構造的所有對象,都會被自動析構
析構的順序與構造的順序相反。這一過程稱為棧的解旋
而堆上的空間,則會泄漏
#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;
}
結果為:
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;
}
結果為:
A()
A(const A &obj)
~A()
no x, no y
~A()
原文鏈接:https://blog.csdn.net/SAKURASANN/article/details/105983755
相關推薦
- 2022-07-15 教你docker方式部署nacos_docker
- 2022-07-10 修改redo默認傳輸用戶sys到其他---redo_transport_user參數
- 2022-07-08 C#使用WebClient實現上傳下載_C#教程
- 2022-09-26 你了解Redis事務嗎_Redis
- 2022-06-25 C#將DataGridView中的數據保存到CSV和Excel中_C#教程
- 2022-04-30 利用Python生成Excel炫酷圖表_python
- 2022-09-30 C#?wpf?Grid中實現控件拖動調整大小的示例代碼_C#教程
- 2022-09-30 AndroidStudio圖片壓縮工具ImgCompressPlugin使用實例_Android
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支