日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學(xué)無先后,達者為師

網(wǎng)站首頁 編程語言 正文

C++?中的異常拋出和捕獲方式_C 語言

作者:止步聽風(fēng) ? 更新時間: 2022-09-17 編程語言

在 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

欄目分類
最近更新