




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
面向?qū)ο蟪绦蛟O(shè)計(jì)第9章
異常處理主要內(nèi)容●
9.1異常處理概述●
9.2異常處理的實(shí)現(xiàn)●
9.3構(gòu)造函數(shù)、析構(gòu)函數(shù)與異常處理●
9.4異常匹配●9.5標(biāo)準(zhǔn)異常及層次結(jié)構(gòu)●
9.6異常處理中需要注意的問題學(xué)習(xí)目標(biāo)掌握了解標(biāo)準(zhǔn)異常處理及層次結(jié)構(gòu)理解異常處理的基本概念掌握編寫異常處理程序理解掌握異常處理的實(shí)現(xiàn)9.1異常處理概述異常就是在程序運(yùn)行中發(fā)生的難以預(yù)料的、不正常的事件而導(dǎo)致偏離正常流程的現(xiàn)象。包括編譯時(shí)發(fā)生的錯(cuò)誤和運(yùn)行時(shí)發(fā)生的錯(cuò)誤,發(fā)生異常將導(dǎo)致正常流程不能進(jìn)行,就需要對(duì)異常進(jìn)行處理。異常存在于程序的正常功能之外,并要求程序立即處理。通過異??梢詫栴}的檢測(cè)和解決分離,方便了程序的開發(fā)和設(shè)計(jì)。異常處理(Exceptionhandling)提供了一種標(biāo)準(zhǔn)的方法以處理錯(cuò)誤,發(fā)現(xiàn)可預(yù)知或不可預(yù)知的問題,允許開發(fā)者識(shí)別、查出和修改錯(cuò)漏之處。使用異常處理,程序中獨(dú)立開發(fā)的各部分能夠就程序執(zhí)行期間出現(xiàn)的問題相互通信,并處理這些問題。異常處理是在運(yùn)行時(shí)刻對(duì)異常進(jìn)行檢測(cè)、捕獲、提示、傳遞等過程。它是C++語言的一個(gè)重要特征,它提出了出錯(cuò)處理更加完美的方法。1.異常、異常處理的概念在編譯時(shí),編譯系統(tǒng)能發(fā)現(xiàn)程序中的語法錯(cuò)誤(如關(guān)鍵字拼寫錯(cuò),變量名未定義,語句末尾缺分號(hào),括號(hào)不配對(duì)等),編譯系統(tǒng)會(huì)告知用戶在第幾行出錯(cuò),是什么樣的錯(cuò)誤。由于是在編譯階段發(fā)現(xiàn)的錯(cuò)誤,因此這類錯(cuò)誤又稱為編譯錯(cuò)誤。有的初學(xué)者寫的并不長(zhǎng)的程序,在編譯時(shí)會(huì)出現(xiàn)十幾個(gè)甚至幾十個(gè)語法錯(cuò)誤,使人往往感到手足無措。但是,總的來說,這種錯(cuò)誤是比較容易發(fā)現(xiàn)和糾正的,因?yàn)樗鼈円话愣际怯幸?guī)律的,在有了一定的編譯經(jīng)驗(yàn)以后,可以很快地發(fā)現(xiàn)出錯(cuò)的位置和原因并加以改正。(1)語法錯(cuò)誤1.異常、異常處理的概念
有的程序雖然能通過編譯,也能投入運(yùn)行,但是在運(yùn)行過程中會(huì)出現(xiàn)異常,得不到正確的運(yùn)行結(jié)果,甚至導(dǎo)致程序不正常終止,或出現(xiàn)死機(jī)現(xiàn)象。例如:①訪問數(shù)組元素的下標(biāo)越界,在越界時(shí)又寫入了數(shù)據(jù)或遇到意外的非法輸入;②用new動(dòng)態(tài)申請(qǐng)內(nèi)存而返回空指針(可能是因內(nèi)存不足);③算術(shù)運(yùn)算上溢出或下溢出;④整數(shù)除法中除數(shù)為0;⑤調(diào)用函數(shù)時(shí)提供了無效實(shí)參,如指針實(shí)參為空指針(如用空指針來調(diào)用strlen函數(shù));⑥通過掛空指針或掛空引用來訪問對(duì)象;⑦輸入整數(shù)或浮點(diǎn)數(shù)失??;⑧I/O錯(cuò)誤。(2)運(yùn)行錯(cuò)誤1.異常、異常處理的概念2.
異常處理的基本思想編程正確性總是依賴某些假設(shè)成立為前提,異常編程就是要分析識(shí)調(diào)用關(guān)系異常傳播方向別這些假設(shè)不成立的情形,采用面向?qū)ο缶幊碳夹g(shù),建立各種異常類型并形成繼承性架構(gòu),以處理程序中可能發(fā)生的各類異常。異常編程的目的是改善程序的可靠性。在大型復(fù)雜的程序中,完全不發(fā)生異常幾乎不可能,用傳統(tǒng)的if-else語句來檢查所有可能的異常情形也有很大困難。出錯(cuò)處理代碼的編寫不再繁瑣錯(cuò)誤發(fā)生是不會(huì)被忽略的圖9-1異常處理模式9.2異常處理的實(shí)現(xiàn)9.2異常處理的實(shí)現(xiàn)C++提供了對(duì)處理異常情況的內(nèi)部支持。C++語言的異常處理語句包括:
引發(fā)異常語句throw和捕獲處理語句try-catch
這兩種語句就是C++語言中用于實(shí)現(xiàn)異常處理的機(jī)制,有了異常處理程序可以向更高的執(zhí)行上下文傳遞意想不到的事件,從而使程序能更好地從這些事件中恢復(fù)過來,異常機(jī)制提供程序中錯(cuò)誤檢測(cè)與錯(cuò)誤處理部分之間的通信。異常處理的語句1.try塊(tryblock)錯(cuò)誤處理部分用它來處理異常。try語句塊以try關(guān)鍵字開始,并以一個(gè)或多個(gè)catch子句結(jié)束。在try塊中執(zhí)行的代碼所拋出(throw)的異常,通常會(huì)被其中一個(gè)catch子句處理。由于它們“處理”異常,catch子句也稱為處理代碼。
try
{ //語句
}try子句中的語句就是代碼的保護(hù)段,這些語句可以是任意C++語句,包括變量聲明,與其它塊語句一樣,try塊引入了局部作用域,塊中聲明的變量不能在外面引用。如果預(yù)料程序有可能發(fā)生異常,則將其放在try塊中。9.2異常處理的實(shí)現(xiàn)2.
throw表達(dá)式(throwexpression)系統(tǒng)通過throw表達(dá)式拋出異常,錯(cuò)誤檢測(cè)部分使用這種表達(dá)式來說明遇到了無法處理的錯(cuò)誤??梢哉f,throw引發(fā)了異常條件。
拋出異常的定義為:
throw表達(dá)式由關(guān)鍵字throw以及尾隨的表達(dá)式組成。其中,表達(dá)式的值稱為一個(gè)異常,所以執(zhí)行throw語句就稱為拋出異常,可以拋出任意類型的一個(gè)值。throw的操作數(shù)在表示異常類型的語法上與return語句的操作數(shù)相似,如果程序中有多處要拋出異常,應(yīng)該使用不同的操作數(shù)進(jìn)行區(qū)別,操作數(shù)的值不能用來區(qū)別不同的異常。執(zhí)行throw語句時(shí),try塊就會(huì)停止執(zhí)行。如果try塊之后有一個(gè)合適的catch塊,控制權(quán)就會(huì)轉(zhuǎn)交catch塊處理。9.2異常處理的實(shí)現(xiàn)【例9-1】處理除零異常的示例/*ch09-1.cpp*/#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;return0;}intDiv(intx,inty){ if(y==0) throwy;//如果除數(shù)為0,拋出整型異常 returnx/y;}【例9-2】打開指定文件,并將10個(gè)整數(shù)寫入文件中。若打開文件失敗,拋出異常。/*ch09-2.cpp*/#include<iostream>#include<fstream>usingnamespacestd;intmain(){ inta[10]={1,2,3,4,5,6,7,8,9,10}; char*filename="d:\\f1.txt"; ofstreamoutfile; outfile.open(filename,ios::out);
try{if(!outfile)throw1;
//拋出異常for(inti=0;i<10;i++) outfile<<a[i]<<""; cout<<endl;}catch(int) //捕獲異常{cout<<"打開文件失?。?<<endl;} return0;}
異常接口聲明編寫異常處理器必須知道被測(cè)試調(diào)用的函數(shù)能拋出哪些類型的異常對(duì)象。C++提供了異常接口聲明,即在函數(shù)原型聲明中,位于參數(shù)表列之后,清晰地告訴函數(shù)的使用者:該函數(shù)可能拋出的異常類型,以便使用者能夠方便地捕獲異常對(duì)象進(jìn)行異常處理。帶有異常接口聲明的函數(shù)原型說明的一般形式:返回類型函數(shù)名(參數(shù)表列)throw異常類型名[,…]使用異常規(guī)格說明的函數(shù)原型有三種:(1)拋出指定類型異常對(duì)象的函數(shù)原型:voidfunction()throw(toobig,toosmall,divzero);(2)能拋出任何類型異常對(duì)象的函數(shù)原型:voidfunction();注意,該形式與傳統(tǒng)的函數(shù)原型聲明形式相同。(3)不拋出任何異常對(duì)象的函數(shù)原型:voidfunction()throw()。9.3構(gòu)造函數(shù)、析構(gòu)函數(shù)與
異常處理C++異常處理具有處理構(gòu)造函數(shù)異常的能力。由于構(gòu)造函數(shù)沒有返回值,如果沒有異常機(jī)制,只能按以下兩種選擇報(bào)告在構(gòu)造期間的錯(cuò)誤:①設(shè)置一個(gè)非局部的標(biāo)志并希望用戶檢查它;②希望用戶檢查對(duì)象是否被完全創(chuàng)建。這是一個(gè)嚴(yán)重的問題,因?yàn)樵贑++程序中,對(duì)象構(gòu)造失敗后繼續(xù)執(zhí)行注定是災(zāi)難。所以構(gòu)造函數(shù)成為拋出異常最重要的用途之一。使用異常機(jī)制是處理構(gòu)造函數(shù)錯(cuò)誤的安全有效的方法。然而用戶還必須把注意力集中在對(duì)象內(nèi)部的指針上和構(gòu)造函數(shù)異常拋出時(shí)的清除方法上。1.在構(gòu)造函數(shù)中拋出異常
2.不要在析構(gòu)函數(shù)中拋出異常由于析構(gòu)函數(shù)會(huì)在拋出異常時(shí)被調(diào)用,所以永遠(yuǎn)不要在析構(gòu)函數(shù)中拋出一個(gè)異?;蛘咄ㄟ^執(zhí)行在析構(gòu)函數(shù)中的動(dòng)作導(dǎo)致其它異常的拋出。否則就意味著在已存在的異常到達(dá)引起捕獲之前又拋出一個(gè)新的異常,這會(huì)導(dǎo)致對(duì)terminate()的調(diào)用。換句話講,假若調(diào)用一個(gè)析構(gòu)函數(shù)中的任何函數(shù)都有可能會(huì)拋出異常,則這些調(diào)用應(yīng)該寫在析構(gòu)函數(shù)中的一個(gè)測(cè)試塊try中,而且析構(gòu)函數(shù)必須自己處理所有自身的異常,即這里的異常都不應(yīng)逃離析構(gòu)函數(shù)內(nèi)部?!纠?-3】測(cè)試構(gòu)造函數(shù)中拋出異常時(shí)析構(gòu)函數(shù)會(huì)不會(huì)被執(zhí)行。/*ch09-3.cpp*/#include<iostream>#include<string>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;}【例9-3】測(cè)試構(gòu)造函數(shù)中拋出異常時(shí)析構(gòu)函數(shù)會(huì)不會(huì)被執(zhí)行。9.4異常匹配異常是通過拋出對(duì)象引發(fā),該對(duì)象的類型決定應(yīng)該激活哪個(gè)處理代碼,異常以類似于將實(shí)參傳遞給函數(shù)的方式拋出和捕獲。函數(shù)在發(fā)生錯(cuò)誤時(shí)能以拋出異常對(duì)象的方式結(jié)束函數(shù)執(zhí)行是建立在假定該異常對(duì)象能被捕獲和處理的前提下的。這一假定在C++中是成立的,這也是異常處理的一個(gè)優(yōu)點(diǎn)。完成函數(shù)調(diào)用時(shí)的異常測(cè)試,異常對(duì)象的捕獲和處理是由try-catch結(jié)構(gòu)實(shí)現(xiàn)的,使得處理程序運(yùn)行錯(cuò)誤的編碼變得方便、有效,并具有完全的結(jié)構(gòu)化和良好的可讀性。該結(jié)構(gòu)的一般形式如下:try{… //被測(cè)試的程序代碼throw…//拋出異常}catch(異常類型異常對(duì)象名){… //異常處理的程序代碼}9.4異常匹配1.捕獲某種類型的異常try{… //可能產(chǎn)生異常的代碼}catch(type1id1){… //處理類型為type1的異常}catch(type2id2){… //處理類型為type1的異常}//…每個(gè)catch語句相當(dāng)于一個(gè)以特定的異常類型為單一參數(shù)的小型函數(shù),標(biāo)識(shí)符id1、id2等如同函數(shù)中的參數(shù)名,如果對(duì)引起該異常對(duì)象拋出的程序運(yùn)行的錯(cuò)誤處理中無須使用異常對(duì)象,則該標(biāo)識(shí)符可省略;異常處理器部分必須緊跟在測(cè)試塊try之后;catch語句與switch語句不同,即每個(gè)case(情況)引起的執(zhí)行需要加入break實(shí)現(xiàn)執(zhí)行的結(jié)束;測(cè)試塊try中不同函數(shù)的調(diào)用可能會(huì)拋出相同的異常對(duì)象,而異常處理器中對(duì)同一異常對(duì)象的處理方法只需要一個(gè)。2.捕獲所有類型的異常catch(…){cout<<“anunkownexceptionwasthrown”<<endl;}3.未捕獲的異常如果測(cè)試塊try執(zhí)行過程中拋出的異常對(duì)象在當(dāng)前異常處理器沒有被捕獲,則異常對(duì)象將進(jìn)入更高一層的運(yùn)行環(huán)境中。這種異常對(duì)象的拋出、捕獲、處理過程按照運(yùn)行環(huán)境的調(diào)用關(guān)系逐層進(jìn)行,直到在某個(gè)層次的運(yùn)行環(huán)境的異常處理器中捕獲并恰當(dāng)處理了異常對(duì)象才停止,否則將一直進(jìn)行至到調(diào)用系統(tǒng)的特定函數(shù)terminate()終止程序運(yùn)行。例如,在異常對(duì)象的創(chuàng)建過程中、異常對(duì)象的被處理過程中或異常對(duì)象的析構(gòu)過程中又拋出了新異常對(duì)象,就會(huì)產(chǎn)生所拋出的異常對(duì)象不能被捕獲?!纠?-4】捕獲多個(gè)異常。/*ch09-4.cpp*/#include<iostream>#include<string>usingnamespacestd;classNegativeNumber{public:NegativeNumber();NegativeNumber(stringcatched);stringget_message();private:stringmessage;};classDivideByZero{};NegativeNumber::NegativeNumber(){}NegativeNumber::NegativeNumber(stringcatched):message(catched){}stringNegativeNumber::get_message(){returnmessage;}intmain(){intchocolatenumber,kidnumber;doublenumber;try{cout<<"請(qǐng)輸入巧克力塊數(shù):\n";cin>>chocolatenumber;if(chocolatenumber<0)throwNegativeNumber("chocolatenumber");cout<<"請(qǐng)輸入小朋友人數(shù):\n";cin>>kidnumber;if(kidnumber<0)throwNegativeNumber("kidnumber");if(kidnumber!=0)number=chocolatenumber/double(kidnumber);elsethrowDivideByZero();cout<<"每個(gè)小朋友分得"<<number<<"巧克力。\n";}
catch(NegativeNumbere){cout<<e.get_message()<<"不能為負(fù)值。"<<endl;}catch(DivideByZero){cout<<"除數(shù)不能為0.\n";}return0;}【例9-4】捕獲多個(gè)異常。9.5標(biāo)準(zhǔn)異常及層次結(jié)構(gòu)
在C++標(biāo)準(zhǔn)庫中提供了一批標(biāo)準(zhǔn)異常類,用于報(bào)告在標(biāo)準(zhǔn)庫中的函數(shù)遇到的問題,為用戶在編程中直接使用和作為派生異常類的基類。下表9-1描述了這些標(biāo)準(zhǔn)異常類。9.5標(biāo)準(zhǔn)異常及層次結(jié)構(gòu)類名說明頭文件exception是所有標(biāo)準(zhǔn)異常類的基類。可以調(diào)用它的成員函數(shù)what()獲取其特征的顯示說明。exceptionlogic_errorexception的派生類,報(bào)告程序邏輯錯(cuò)誤,這些錯(cuò)誤在程序執(zhí)行前可以被檢測(cè)到。stdexceptruntime_errorexception的派生類,報(bào)告程序運(yùn)行錯(cuò)誤,這些錯(cuò)誤僅在程序運(yùn)行時(shí)可以被檢測(cè)到。stdexceptios_base::failureException的派生類,報(bào)告I/O操作錯(cuò)誤,ios_base::clear()可能拋出該異常類對(duì)象。iosbase表9-1標(biāo)準(zhǔn)異常類圖9.1標(biāo)準(zhǔn)異常層次結(jié)構(gòu)9.5標(biāo)準(zhǔn)異常及層次結(jié)構(gòu)9.6異常處理中需要注意的問題
使用任何一個(gè)新特性必然有所開銷。異常被拋出需要開銷相當(dāng)?shù)倪\(yùn)行時(shí)間,這就是不要把異常處理用于程序流控制的一部分原因
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(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ì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 員工職業(yè)心態(tài)課件
- 慢性胃炎的食療調(diào)養(yǎng)課件
- 《期末考試總動(dòng)員》課件
- 《調(diào)度操作規(guī)程》課件
- 《cA水利工程》課件
- 《隧道爆破技術(shù)》課件
- 2025至2031年中國機(jī)械防震腳墊行業(yè)投資前景及策略咨詢研究報(bào)告
- 2025至2031年中國快速液壓機(jī)行業(yè)投資前景及策略咨詢研究報(bào)告
- 2025至2031年中國安全路錐行業(yè)投資前景及策略咨詢研究報(bào)告
- 《電力監(jiān)控系統(tǒng)介紹》課件
- 安全性測(cè)試方案(完整版)
- 《PLC與變頻器控制》課件 3.多段速控制
- 魯迅吶喊讀書分享名著導(dǎo)讀
- 第1.1課-七律二首-送瘟神-【中職專用】高二語文同步備課課件(高教版2023職業(yè)模塊)
- YB-4001.1-2007鋼格柵板及配套件-第1部分:鋼格柵板(中文版)
- 初中語文跨學(xué)科資源融合教學(xué)研究
- 2023年廣西區(qū)考公務(wù)員錄用考試《行測(cè)》(含答案及解析)【可編輯】
- 傷寒診療指南
- 春秋季六年級(jí)奧數(shù)培訓(xùn)教材全0
- 【實(shí)用資料】食物中毒現(xiàn)場(chǎng)衛(wèi)生學(xué)采樣PPT
- 鋼結(jié)構(gòu)工程施工施工質(zhì)量控制與驗(yàn)收
評(píng)論
0/150
提交評(píng)論