《C++面向?qū)ο蟪绦蛟O(shè)計(jì)》課件第9章_第1頁(yè)
《C++面向?qū)ο蟪绦蛟O(shè)計(jì)》課件第9章_第2頁(yè)
《C++面向?qū)ο蟪绦蛟O(shè)計(jì)》課件第9章_第3頁(yè)
《C++面向?qū)ο蟪绦蛟O(shè)計(jì)》課件第9章_第4頁(yè)
《C++面向?qū)ο蟪绦蛟O(shè)計(jì)》課件第9章_第5頁(yè)
已閱讀5頁(yè),還剩42頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(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ì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論