版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
9.1異常的概念(ExceptionConcept)9.2異常處理機(jī)制及意義
(MechanismandSignificanceofExceptionHandling )9.3標(biāo)準(zhǔn)異常(StandardException) 9.4異常的捕獲和處理
(ExceptionCatchingandHandling)
9.5異常處理中的構(gòu)造與析構(gòu)
(ConstructorandDestructorinExceptionHandling) 9.6開(kāi)銷(Spending) 9.7常見(jiàn)編程錯(cuò)誤(CommonProgrammingErrors)本章小結(jié)(ChapterSummary)
習(xí)題9(Exercises9)
異常是指程序運(yùn)行時(shí)出現(xiàn)的不正常情況,包括運(yùn)行時(shí)發(fā)生的錯(cuò)誤,如除數(shù)為零、存儲(chǔ)空間不足或遇到意外的非法輸入等等。異常存在于程序的正常功能之外,并要求程序立即處理。通過(guò)異??梢詫?wèn)題的檢測(cè)和解決分離,方便了程序的開(kāi)發(fā)和設(shè)計(jì)。
異常處理提供了一種標(biāo)準(zhǔn)的方法以處理錯(cuò)誤,發(fā)現(xiàn)可預(yù)知或不可預(yù)知的問(wèn)題。這種方法允許開(kāi)發(fā)者識(shí)別、查出和修改錯(cuò)漏之處。使用異常處理,程序中獨(dú)立開(kāi)發(fā)的各部分能夠就程序執(zhí)行期間出現(xiàn)的問(wèn)題相互通信,并處理這些問(wèn)題。9.1異?常?的?概?念(ExceptionConcept)
1.try塊(tryblock)
錯(cuò)誤處理部分用try塊來(lái)處理異常。
2.throw表達(dá)式(throwexpression)
系統(tǒng)通過(guò)throw表達(dá)式拋出異常,錯(cuò)誤檢測(cè)部分使用這種表達(dá)式來(lái)說(shuō)明遇到了無(wú)法處理的錯(cuò)誤。
3.由標(biāo)準(zhǔn)庫(kù)定義的一組異常類
由標(biāo)準(zhǔn)庫(kù)定義的一組異常類用來(lái)在throw和相應(yīng)的catch之間傳遞有關(guān)的錯(cuò)誤信息。9.2異常處理機(jī)制及意義(MechanismandSignificanceofExceptionHandling)在C++?標(biāo)準(zhǔn)庫(kù)中提供了一批標(biāo)準(zhǔn)異常類,用于報(bào)告在標(biāo)準(zhǔn)庫(kù)中的函數(shù)遇到的問(wèn)題,為用戶在編程中直接使用和作為派生異常類的基類。
表9-1描述了這些標(biāo)準(zhǔn)異常類。9.3標(biāo)準(zhǔn)異常(StandardException)表9-1標(biāo)?準(zhǔn)?異?常?類異常通過(guò)拋出對(duì)象引發(fā),該對(duì)象的類型決定應(yīng)該激活哪個(gè)處理代碼。異常以類似于將實(shí)參傳遞給函數(shù)的方式拋出和捕獲。完成函數(shù)調(diào)用時(shí)的異常測(cè)試,其異常對(duì)象的捕獲和處理由try-catch結(jié)構(gòu)實(shí)現(xiàn),使得處理程序運(yùn)行錯(cuò)誤的編碼變得方便、有效,并具有完全的結(jié)構(gòu)化和良好的可讀性。try-catch結(jié)構(gòu)的一般形式如下:9.4異常的捕獲和處理(ExceptionCatchingandHandling)try
{
… //被測(cè)試的程序代碼
}
catch(異常類型異常對(duì)象名)
{
… //異常處理的程序代碼
}9.4.1try塊(tryBlock)
try塊以關(guān)鍵字try開(kāi)始,后面是用花括號(hào)括起來(lái)的語(yǔ)句序列塊。
try塊的定義格式如下:
try
{
語(yǔ)句
}【例9-1】
如果new或new[]不能分配所請(qǐng)求的存儲(chǔ)空間,將拋出一個(gè)bad_alloc異常??梢酝ㄟ^(guò)如下方式檢測(cè)存儲(chǔ)空間的分配是否失敗:
int*ptr;
…//其他代碼
try{
//可能產(chǎn)生異常的語(yǔ)句
ptr=newint;}
catch(bad_alloc){
cerr<<"new:unabletoallocatestorage…aborting\n";
exit(EXIT_FAILURE); //EXIT_FAILURE定義在頭文件cstdlib.h中
}
… //分配成功后執(zhí)行的代碼9.4.2throw表達(dá)式(throwExpression)
拋出異常的定義為throw表達(dá)式,由關(guān)鍵字throw以及尾隨的表達(dá)式組成。其中,表達(dá)式的值稱為一個(gè)異常,執(zhí)行throw語(yǔ)句就稱為拋出異常。
【例9-2】
處理除零異常的示例。
#include<iostream>
usingnamespacestd;
intDiv(intx,inty);intmain()
{
try{//除法可能產(chǎn)生除0異常,因此將代碼放入try塊中
cout<<"5/2="<<Div(5,2)<<endl;
cout<<"8/0="<<Div(8,0)<<endl;
cout<<"7/1="<<Div(7,1)<<endl;
}
catch(int)
{ cout<<"除數(shù)為0"<<endl;
}
cout<<"that’sok."<<endl;
}
intDiv(intx,inty)
{
if(y==0)
throwy; //如果除數(shù)為0,拋出整型異常
returnx/y;
}程序運(yùn)行結(jié)果如下:
5/2=2
除數(shù)為0
that’sok.9.4.3異常處理器(ExceptionHandler)
異常發(fā)生后,被拋出的異常對(duì)象一旦被隨后的異常處理器捕獲到,就可以被處理。根據(jù)在當(dāng)前運(yùn)行環(huán)境中能否解決引起異常的程序運(yùn)行錯(cuò)誤,對(duì)異常對(duì)象的處理有兩種:
(1)嘗試解決程序運(yùn)行錯(cuò)誤,析構(gòu)異常對(duì)象。
(2)若無(wú)法解決程序運(yùn)行錯(cuò)誤,則將異常對(duì)象拋向上一層運(yùn)行環(huán)境。為此,異常處理器應(yīng)該具備捕獲一個(gè)以上任何類型異常對(duì)象的能力,每個(gè)異常對(duì)象的捕獲和處理由關(guān)鍵字catch引導(dǎo)。例如:
try
{
… //可能產(chǎn)生異常的代碼
}
catch(type1id1)
{
… //處理類型為type1的異常}
catch(type2id2)
{
… //處理類型為type1的異常
}
//…異常處理包括兩種模式:終止模式和恢復(fù)模式。
1.終止模式
如果引起異常的是致命錯(cuò)誤,即表明程序運(yùn)行進(jìn)入了無(wú)法恢復(fù)正常運(yùn)行的狀態(tài),這時(shí)必須調(diào)用終止模式結(jié)束程序運(yùn)行的異常狀態(tài),而不應(yīng)返回異常拋出之處。
2.恢復(fù)模式
恢復(fù)意味著期望能夠修復(fù)異常狀態(tài),然后再次對(duì)拋出異常對(duì)象的函數(shù)進(jìn)行測(cè)試調(diào)用,使之能夠成功運(yùn)行。9.4.4異常規(guī)格說(shuō)明(ExceptionSpecification)
編寫(xiě)異常處理器必須知道被測(cè)試調(diào)用的函數(shù)能拋出哪些類型的異常對(duì)象。帶有異常規(guī)格說(shuō)明的函數(shù)原型說(shuō)明的一般形式為:
返回類型函數(shù)名(參數(shù)表列)throw異常類型名[,…]使用異常規(guī)格說(shuō)明的函數(shù)原型有三種:
(1)拋出指定類型異常對(duì)象的函數(shù)原型:
voidfunction()throw(toobig,toosmall,divzero);
(2)能拋出任何類型異常對(duì)象的函數(shù)原型:
voidfunction();
注意,該形式與傳統(tǒng)的函數(shù)原型聲明形式相同。
(3)不拋出任何異常對(duì)象的函數(shù)原型:
voidfunction()throw();自定義處理方法的設(shè)定通過(guò)調(diào)用系統(tǒng)函數(shù)set_unexpected(…)完成,該函數(shù)的原型如下:
typedefvoid(*unexpected_function)();
unexpected_functionset_unexpected(unexpected_functionunexp_func);
該函數(shù)可以將一個(gè)自定義的處理函數(shù)地址unexp_func設(shè)置為unexpected的函數(shù)指針新值,并返回該指針的當(dāng)前值,以便保存,并用于恢復(fù)原處理方法。9.4.5捕獲所有類型的異常
(CatchingallkindsofExceptions)
如果函數(shù)定義時(shí)沒(méi)有異常規(guī)格說(shuō)明,則在該函數(shù)被調(diào)用時(shí)就有可能拋出任何類型的異常對(duì)象。為了解決這個(gè)問(wèn)題,應(yīng)該在異常處理器中增加一個(gè)能捕獲任意類型的異常對(duì)象的處理分支。例如:
catch(…)
{
cout<<“anunkownexceptionwasthrown”<<endl;
}9.4.6未捕獲的異常(UncaughtExceptions)
如果測(cè)試塊try執(zhí)行過(guò)程中拋出的異常對(duì)象在當(dāng)前異常處理器沒(méi)有被捕獲,則異常對(duì)象將進(jìn)入更高一層的運(yùn)行環(huán)境中。9.5.1在構(gòu)造函數(shù)中拋出異常
(ThrowingExceptionsinConstructor)
由于構(gòu)造函數(shù)沒(méi)有返回值,如果沒(méi)有異常機(jī)制,只能按以下兩種選擇報(bào)告在構(gòu)造期間的錯(cuò)誤:
(1)設(shè)置一個(gè)非局部的標(biāo)志并希望用戶檢查它。
(2)希望用戶檢查對(duì)象是否被完全創(chuàng)建。9.5異常處理中的構(gòu)造與析構(gòu)(ConstructorandDestructorinExceptionHandling)9.5.2不要在析構(gòu)函數(shù)中拋出異常
(NottoThrowExceptionsinDestructor)
由于析構(gòu)函數(shù)會(huì)在拋出異常時(shí)被調(diào)用,所以永遠(yuǎn)不要在析構(gòu)函數(shù)中拋出一個(gè)異常或者通過(guò)執(zhí)行在析構(gòu)函數(shù)中的動(dòng)作導(dǎo)致其他異常的拋出,否則就意味著在已存在的異常到達(dá)引起捕獲之前又拋出一個(gè)新的異常,這會(huì)導(dǎo)致對(duì)terminate()的調(diào)用?!纠?-3】
測(cè)試構(gòu)造函數(shù)中拋出異常時(shí)析構(gòu)函數(shù)會(huì)不會(huì)被執(zhí)行。
#include<iostream>
usingnamespacestd;
classMyTest_Base
{
public:
MyTest_Base(stringname="")::m_name(name){
throwstd::exception(“在構(gòu)造函數(shù)中拋出一個(gè)異常,測(cè)試!”);
cout<<“構(gòu)造一個(gè)MyTest_Base類型對(duì)象,對(duì)象名為:”<<m_name<<endl;
}
virtual~MyTest_Base(){
cout<<“銷毀一個(gè)MyTest_Base類型對(duì)象,對(duì)象名為:”<<m_name<<endl;
}
voidFunc()throw()
{
throwstd::exception("故意拋出一個(gè)異常,測(cè)試!");
}
voidOther(){}
protected:
stringm_name;
};
intmain()
{
try
{
//對(duì)象構(gòu)造時(shí)將會(huì)拋出異常
MyTest_Baseobj1(“obj1”);
obj1.Func();
obj1.Other();
}
catch(std::exceptione)
{
cout<<e.what()<<endl;
}
catch(...)
{
cout<<“unknowexception”<<endl;
}
Return0;
}使用任何一個(gè)新特性必然有所開(kāi)銷。異常被拋出需要開(kāi)銷相當(dāng)?shù)倪\(yùn)行時(shí)間,這就是不要把異常處理用于程序流控制的原因之一。相對(duì)于程序的正常執(zhí)行,異常偶而發(fā)生。因此設(shè)計(jì)異常處理的重要目標(biāo)之一是:當(dāng)異常沒(méi)有發(fā)生時(shí),異常處理代碼應(yīng)不影響運(yùn)行速度。換句話說(shuō),只要不拋出異常,代碼的運(yùn)行速度如同沒(méi)有添加異常處理代碼時(shí)一樣。這是因?yàn)楫惓L幚泶a的編譯都依賴于使用特定的編譯器。9.6開(kāi)銷(Spending)
1.當(dāng)有幾個(gè)catch語(yǔ)句塊對(duì)應(yīng)于try語(yǔ)句塊時(shí),catch語(yǔ)句塊捕捉的錯(cuò)誤是按序進(jìn)行的。第一個(gè)與異常值相匹配的catch語(yǔ)句塊總是最先被執(zhí)行。
catch(NegativeNumbere)
{
cout<<"Cannothaveanegativenumberof"
<<e.get_message()<<endl;9.7常見(jiàn)編程錯(cuò)誤(CommonProgrammingErrors)}
catch(DivideByZero)
{
cout<<"Sendforhelp.\n";
這個(gè)catch語(yǔ)句塊將可以捕捉到任何尚未捕捉到的異常
}
catch(...)
{
cout<<"Unexplainedexception.\n";
}
//如果我們將catch(…)語(yǔ)句塊放在中間位置catch(NegativeNumbere)//NegativeNumber引發(fā)的異常仍然可以正常處理
{
cout<<"Cannothaveanegativenumberof"
<<e.get_message()<<endl;
}
catch(...)//但所有其他的異常將在這里被捕捉到
{cout<<"Unexplainedexception.\n";
}
catch(DivideByZero)//DivideByZero異常永遠(yuǎn)也無(wú)法捕捉到
{
cout<<"Sendforhelp.\n";
}//處在catch(…)語(yǔ)句塊下面的異常均將無(wú)法正常得到處理。大多數(shù)編譯器可以“捕捉”到
//這個(gè)錯(cuò)誤。
2.代碼異常沒(méi)有被捕捉,所有異常都應(yīng)在代碼的某個(gè)地方捕捉,如果異常拋出后沒(méi)有捕捉到,則程序會(huì)終止。
3.析構(gòu)函數(shù)絕對(duì)不能拋出異常。
4.如果在派生類中覆蓋或重定義一個(gè)成員函數(shù),就要求在派生類中具有與基類中相同的異常列表,或者異常列表是基類函數(shù)中異常列表的子集亦可。
5.程序中扔出的每一個(gè)異常都應(yīng)該在程序中的某個(gè)地方能夠捕獲。
6.可以將try-throw-catch語(yǔ)句嵌套至另一個(gè)try語(yǔ)句塊或者是catch語(yǔ)句塊中。
7.異常被拋出后,catch處理程序出現(xiàn)的順序很重要。例如下面這段程序:
//…
try
{
//…
}
catch(…)
{ //所有的異常均被接收在此處
}
catch(constchar*str)//該子句不會(huì)被執(zhí)行
{
cout<<"Caughtexception:"<<str<<endl;
}
應(yīng)該將catch(…)子句放在最后。
8.建議將異常只用于簡(jiǎn)單的程序中。錯(cuò)誤的處理和恢復(fù)是和用戶編寫(xiě)每個(gè)程序都密切相關(guān)的基本原則,在C++?中尤其重要,創(chuàng)建程序組件為其他人重用是開(kāi)發(fā)的目標(biāo)之一。C++?中異常處理的目標(biāo)是簡(jiǎn)化大型可靠程序的創(chuàng)建,使用盡可能少的代碼,使應(yīng)用中沒(méi)有不受控制的錯(cuò)誤。異常處理幾乎不損害性能,并且對(duì)其他代碼的影響很小。在C++的異常處理中,try塊語(yǔ)句包含一個(gè)可能拋出異常的語(yǔ)句序列,catch子句用來(lái)處理在try塊里拋出的異常,throw表達(dá)式用于退出代碼塊的運(yùn)行,將控制轉(zhuǎn)移給相關(guān)的catch子句。本章小結(jié)(ChapterSummary)一、填空題
1.C++程序?qū)⒖赡馨l(fā)生異常的程序塊放在
中,緊跟其后可放置若干對(duì)應(yīng)的
,在前面所說(shuō)的塊中或塊所調(diào)用的函數(shù)中應(yīng)該有對(duì)應(yīng)的
,由它在不正常時(shí)拋出
,如與某一條
類型相匹配,則執(zhí)行該語(yǔ)句。該語(yǔ)句執(zhí)行完后,如未退出程序,則執(zhí)行
。如沒(méi)有匹配的語(yǔ)句,則交C++標(biāo)準(zhǔn)庫(kù)中的
處理。
2.異常也適用類的層次結(jié)構(gòu),與虛函數(shù)的規(guī)則
,基類的異常
派生類異常catch子句處理,而反過(guò)來(lái)則
。習(xí)題9(Exercises9)
3.異常處理時(shí)與函數(shù)重載
,異常處理是由
catch子句處理,而不是由
catch子句處理,所以catch子句
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 《設(shè)備保養(yǎng)的重要性》課件
- 《政府公共禮品》課件
- 2025屆福建省上杭縣一中高三壓軸卷數(shù)學(xué)試卷含解析
- 山東省濰坊市第一中學(xué)2025屆高三最后一卷英語(yǔ)試卷含解析
- 江西省上高縣第二中學(xué)2025屆高三二診模擬考試語(yǔ)文試卷含解析
- 甘肅肅蘭州市第五十一中學(xué)2025屆高考英語(yǔ)五模試卷含解析2
- 湖北省鋼城四中2025屆高三下第一次測(cè)試語(yǔ)文試題含解析
- 廣西壯族自治區(qū)欽州市2025屆高三最后一卷語(yǔ)文試卷含解析
- 湖北省隨州一中2025屆高考數(shù)學(xué)倒計(jì)時(shí)模擬卷含解析
- 浙江教育綠色評(píng)價(jià)聯(lián)盟2025屆高三最后一卷語(yǔ)文試卷含解析
- 中國(guó)平安保險(xiǎn)公司薪酬體系
- 坡比與角度換算表
- 機(jī)械制圖基礎(chǔ)知識(shí)
- 靜脈治療小組工作計(jì)劃_
- 施工現(xiàn)場(chǎng)臨時(shí)用電驗(yàn)收記錄(新)2頁(yè)
- 入團(tuán)志愿書(shū)(2016版本)(可編輯打印標(biāo)準(zhǔn)A4)
- (完整word版)北師大版四年級(jí)數(shù)學(xué)上冊(cè)運(yùn)算律練習(xí)
- 淺談測(cè)繪技術(shù)的應(yīng)用及質(zhì)量控制
- 電氣設(shè)備安裝及調(diào)試重要性分析
- 2019年12月六級(jí)第一套(含答案)
- 3、模塊手冊(cè)(下)
評(píng)論
0/150
提交評(píng)論