C++拋出和接收異常的順序
異常(exception)是C++語言引入的錯誤處理機(jī)制。它 采用了統(tǒng)一的方式對程序的運行時錯誤進(jìn)行處理,具有標(biāo)準(zhǔn)化、安全和高效的特點。C++為了實現(xiàn)異常處理,引入了三個關(guān)鍵字:try、throw、catch。異常由throw拋出,格式為throw[expression],由catch捕捉。Try語句塊是可能拋出異常的語句塊,它通常和一個或多個catch語句塊連續(xù)出現(xiàn)。
try語句塊和catch語句塊必須相互配合,以下三種情況都會導(dǎo)致編譯錯誤:
(1)只有try語句塊而沒有catch語句塊,或者只有catch語句塊而沒有try語句塊;
(2)在try語句塊和catch語句塊之間夾雜有其他語句;
(3)當(dāng)try語句塊后跟有多個catch語句塊時,catch語句塊之間夾雜有其他語句;
(4)同一種數(shù)據(jù)類型的傳值catch分支與傳引用catch分支不能同時出現(xiàn)。
在拋出和接收異常的過程中,我們還要注意以下幾點。
1.被拋出的異常對象什么時候被銷毀?
用throw語句拋出一個對象時,會構(gòu)造一個新的對象,這個對象就是異常對象。該對象的生命周期從被拋出開始計算,一直到被某個catch語句捕捉,就會在該catch語句塊執(zhí)行完畢后被銷毀??疾烊缦鲁绦?。
#include <iostream> using namespace std; class ExClass { int num; public: ExClass(int i) { cout<<"Constructing exception object with num="<<i<<endl; num=i; } ExClass(ExClass& e) { cout<<"Copy Constructing exception object with num="<<e.num+1<<endl; num=e.num+1; } ~ExClass() { cout<<"Destructing exception object with num="<<num<<endl; } void show() { cout<<"the number is "<<num<<endl; } }; int main() { ExClass obj(99); try { throw obj; //導(dǎo)致輸出:Constructing exception object with num=100 } catch(double f) { cout<<"exception catched"<<endl; } //導(dǎo)致輸出:Constructing exception object with num=101 catch(ExClass e) { e.show(); } cout<<"after catch"<<endl; }
程序輸出結(jié)果是:
Constructing exception object with num=99
Copy Constructing exception object with num=100
Copy Constructing exception object with num=101
the number is 101
Destructing exception object with num=101
Destructing exception object with num=100
after catch
Destructing exception object with num=99
用throw語句拋出一個對象時,會構(gòu)造一個新的對象,這個對象就是異常對象。該對象的生命周期從被拋出時開始計算,一直到被某個catch語句捕獲,就會在該catch語句塊執(zhí)行完畢后被銷毀。在上面的程序中,異常對象的num值為100,“Destructing exception object with num=100”這句話在“after catch”之前輸出,正好說明異常對象的銷毀時間是在它被捕獲的catch塊執(zhí)行之后。
所以的catch分支在執(zhí)行時類似一次函數(shù)調(diào)用,catch 的參數(shù)相當(dāng)于函數(shù)的形參,而被拋出的異常對象相當(dāng)于函數(shù)調(diào)用時的實參。當(dāng)形參與實參成功匹配時,就說明異常被某個catch分支所捕獲。catch后面的參數(shù)只能采用傳值、傳引用和傳指針三種方式,如果采用傳值方式,則會生成實參的一個副本,如果實參是一個對象,就會導(dǎo)致構(gòu)造函數(shù)被調(diào)用。在上面的程序中,執(zhí)行catch(ExClass e) 語句就是利用異常對象構(gòu)造一個對象e,因此會調(diào)用拷貝構(gòu)造函數(shù)。
要注意的是:同一種數(shù)據(jù)類型的傳值catch分支和傳引用catch分支不能同時出現(xiàn)。
2.異常如果在當(dāng)前函數(shù)沒有被捕獲會發(fā)生什么?
在某些情況下,可能所有的catch分支都無法捕獲到拋出的異常,這將導(dǎo)致當(dāng)前函數(shù)執(zhí)行的結(jié)束,并返回到主調(diào)函數(shù)中。在主調(diào)函數(shù)中,將繼續(xù)以上的捕捉異常的過程,直到異常被捕捉或最終結(jié)束整個程序。考察如下程序。
#include <iostream> using namespace std; class ExClass { int num; public: ExClass(int i) { cout<<"Constructing exception object with num="<<i<<endl; num=i; } ExClass(ExClass& e) { cout<<"Copy Constructing exception object with num="<<e.num+1<<endl; num=e.num+1; } ~ExClass() { cout<<"Destructing exception object with num="<<num<<endl; } void show() { cout<<"the number is "<<num<<endl; } }; void throwExFunc() { try{ throw ExClass(199); } catch(double f){ cout<<"double exception catched"<<endl; } cout<<"exit throwExFunc()"<<endl; } int main() { try { throwExFunc(); } catch(ExClass e) { e.show(); } catch(...) { cout<<"all will fall in"<<endl; } cout<<"continue to execute"<<endl; }
程序的輸出結(jié)果:
Constructing exception object with num=199
Copy Constructing exception object with num=200
the number is 200
Destructing exception object with num=200
Destructing exception object with num=199
continue to execute
從程序的結(jié)果可以看出:
(1)被拋出的異常對象的num值為199,由于它沒有在函數(shù)throwExFunc()中被捕捉,所以它導(dǎo)致了throwExFunc()的執(zhí)行結(jié)束(否則會輸出:exit throwExFunc())。在main()函數(shù)中,catch(ExClass e)捕獲了異常對象,通過復(fù)制構(gòu)造函數(shù)產(chǎn)生對象e,e的num值為200,catch語句塊運行完結(jié)束后,對象e首先被銷毀,緊接著銷毀異常對象。在這之后,程序繼續(xù)運行,輸出:continue to execute。
(2)catch(…)的意思是可以捕獲所有類型的異常。不提倡隨意地使用catch(…),因為這會導(dǎo)致異常類型的不精確處理,并降低程序的運行效率。但是,在程序的開發(fā)階段,catch(…)還是有用的,因為如果在精心安排異常捕獲之后,還是進(jìn)入了catch(…)語句塊,說明前面的代碼存在缺陷,需要進(jìn)一步改正。
(3)在捕捉異常對象時,還可以采用傳引用的方式,例如把catch語句寫成catch(ExClass& e),這樣就可以不必產(chǎn)生異常對象的副本,減少程序的運行開銷,提高運行效率。
(4)在拋出異常時,還可以拋出一個指針。當(dāng)然這種做法并不總是安全的。如果要確保安全,應(yīng)該將指針指向全局(靜態(tài))對象的指針或指向動態(tài)申請的空間,或者被拋出的指針在本函數(shù)內(nèi)被捕獲。否則,利用一個被拋出的指向已經(jīng)被銷毀的對象指針很危險。如果實在要用,首先,必須保證對象的析構(gòu)函數(shù)不能對對象的內(nèi)容作損傷性的修改,其次,對象的空間沒有被其他新產(chǎn)生的變量覆蓋。也就說,盡管對象被釋放,但它的有效內(nèi)容依然保留在棧中。
以上就是C++拋出和接收異常的順序的詳細(xì)內(nèi)容,更多關(guān)于C++拋出和接收異常的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Qt顯示QImage圖像在label上,并保持自適應(yīng)大小問題
這篇文章主要介紹了Qt顯示QImage圖像在label上,并保持自適應(yīng)大小問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-11-11淺談C語言中的強(qiáng)符號、弱符號、強(qiáng)引用和弱引用
這篇文章主要介紹了C語言中的強(qiáng)符號、弱符號、強(qiáng)引用和弱引用的定義及相關(guān)內(nèi)容,非常的簡單易懂,有需要的朋友可以參考下2014-10-10