第13章 異常處理_第1頁
第13章 異常處理_第2頁
第13章 異常處理_第3頁
第13章 異常處理_第4頁
第13章 異常處理_第5頁
已閱讀5頁,還剩13頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

第13章異常處理

C++語言程序設(shè)計(jì)教程第11章C++輸入輸出流1第13章

異常處理

學(xué)習(xí)目標(biāo)

掌握try-throw-catch異常處理機(jī)制;能使用異常處理機(jī)制處理程序中常見的異常;了解標(biāo)準(zhǔn)異常處理類的內(nèi)容;能用標(biāo)準(zhǔn)異常處理類處理new、越界類型的異常;C++語言程序設(shè)計(jì)教程第13章異常處理2

一般而言,即使寫得很好的程序也可能遇到錯(cuò)誤和異常情況。在一個(gè)軟件系統(tǒng)中,各個(gè)軟件之間是相互依賴的,它們離不開諸如網(wǎng)絡(luò)系統(tǒng)、文件系統(tǒng)等外部設(shè)施,以及第三方插件、函數(shù)庫等外部代碼,而且還依賴用戶的輸入,這些都可能產(chǎn)生異常情況,當(dāng)異常發(fā)生時(shí),若不對(duì)其加以控制和處理,程序往往可能會(huì)終止運(yùn)行或出現(xiàn)莫名其妙的情況,甚至導(dǎo)致系統(tǒng)的崩潰。因此,在程序設(shè)計(jì)時(shí),當(dāng)實(shí)現(xiàn)分析程序運(yùn)行時(shí)可能出現(xiàn)的“異?!鼻闆r,做好“發(fā)現(xiàn)”異常的準(zhǔn)備,并且,在“異?!卑l(fā)生時(shí),要針對(duì)不同的“異?!鼻闆r進(jìn)行相應(yīng)的處理。一般而言,異常的檢測和處理要完成下列任務(wù)之一:

1)讓“用戶”知道程序出現(xiàn)了異常,允許“用戶”選擇異常處理方式,并繼續(xù)使用程序。

2)讓“用戶”知道程序出現(xiàn)了異常,退出程序的執(zhí)行,并做好系統(tǒng)資源回收等“善后”工作,盡量不影響計(jì)算機(jī)系統(tǒng)中其它程序的正常運(yùn)行。

3)在程序發(fā)生異常時(shí),能夠根據(jù)預(yù)先設(shè)定的異常處理策略進(jìn)行異常處理,能夠在不打擾“用戶”的情況下繼續(xù)程序的運(yùn)行。C++語言程序設(shè)計(jì)教程第13章異常處理1.異常的概念

3

異常是一種錯(cuò)誤處理機(jī)制。程序的錯(cuò)誤通常包括:語法錯(cuò)誤、邏輯錯(cuò)誤、運(yùn)行異常。語法錯(cuò)誤出現(xiàn)在程序編譯時(shí),稱為編譯時(shí)錯(cuò)誤,邏輯錯(cuò)誤和運(yùn)行錯(cuò)誤出現(xiàn)在程序運(yùn)行時(shí),稱為運(yùn)行時(shí)錯(cuò)誤(run-time)。

語法錯(cuò)誤指在編寫程序時(shí),程序中的關(guān)鍵字拼寫錯(cuò)、標(biāo)識(shí)符未定義、控制結(jié)構(gòu)不完整、程序語句不合乎編譯器的語法規(guī)則等等,這種錯(cuò)誤在編譯、連接時(shí)由編譯器指出。

邏輯錯(cuò)誤是指由于編程者對(duì)問題的理解不夠造成算法設(shè)計(jì)有誤,導(dǎo)致程序雖然能順利運(yùn)行,但是沒有得到預(yù)期的結(jié)果,這類錯(cuò)誤通過調(diào)試與測試發(fā)現(xiàn)。

運(yùn)行異常(exception)是指指程序在運(yùn)行的過程中由于意外的結(jié)果,運(yùn)行環(huán)境問題造成程序異常終止,如內(nèi)存空間不足、打開文件不存在、文件讀寫不成功、執(zhí)行了除0操作等。導(dǎo)致程序運(yùn)行錯(cuò)誤雖然是無法避免,但是可以預(yù)料,為了保證程序的健壯性,必須要在程序中對(duì)運(yùn)行錯(cuò)誤進(jìn)行預(yù)見性處理。

C++的異常處理機(jī)制可以在一定程度上減少程序異常所帶來的風(fēng)險(xiǎn),提高程序的健壯性。C++語言程序設(shè)計(jì)教程第13章異常處理1.異常的概念

4

處理異常的方法很多,其中最直接的辦法是調(diào)用C++中的exit()或abort()函數(shù)終止程序的執(zhí)行,exit()與abort()函數(shù)原型在頭文件Cstdlib中聲明,兩者的區(qū)別是exit()在中止程序運(yùn)行前,會(huì)關(guān)閉被程序打開的文件、調(diào)用全局和static類型對(duì)象的析構(gòu)函數(shù)等;而abort()什么都不做。使用exit()與abort()來處理異常顯得很機(jī)械,有的異常需要進(jìn)行更復(fù)雜的處理。以往的異常捕獲方式是利用if語句檢查調(diào)用函數(shù)的返回值,或者在函數(shù)調(diào)用之前檢查,如在求兩個(gè)數(shù)的商時(shí)就需要在函數(shù)前檢查除數(shù)是否為0來捕獲、防止異常:

floatquotient(inta,intb){returna/(float)b;}…cin>>a>>b;if(b==0)//捕獲異常

cout<<"Divide0!"<<endl;else cout<<a<<"/"<<b<<"="<<quotient(a,b);C++語言程序設(shè)計(jì)教程第13章異常處理2.異常處理

5

這種處理機(jī)制有如下缺點(diǎn):

(1)

每使用quotient()一次,就必須利用if語句檢查一次,使得程序?qū)φ?zhí)行過程的描述與對(duì)異常的處理交織在一起,程序的易讀性不好。

(2)

若異常信息在函數(shù)中返回,會(huì)破壞程序的邏輯性。如:原來沒有返回值的函數(shù),要定義成返回值;對(duì)原來有返回值的函數(shù)無法定義異常信息返回;象構(gòu)造函數(shù)、析構(gòu)函數(shù)這類由程序自動(dòng)調(diào)用,又沒有返回值的特殊函數(shù),就沒有辦法利用返回值返回異常。

為此,C++提供了異常處理解決方案。C++語言程序設(shè)計(jì)教程第13章異常處理2.異常處理

6

C++的異常處理引入了3個(gè)關(guān)鍵字try(檢測異常)、throw(拋出異常)和catch(捕獲異常),利用這種結(jié)構(gòu)化的形式來描述異常處理過程。

try負(fù)責(zé)監(jiān)視可能出現(xiàn)異常的程序段,當(dāng)程序運(yùn)行中出現(xiàn)異常時(shí),它會(huì)檢測出這個(gè)異常,程序?qū)⒉荒茉傺刂5某绦蜻壿嬄窂角斑M(jìn)。

throw

負(fù)責(zé)拋出異常,并將程序控制權(quán)交給catch子句。

catch負(fù)責(zé)捕獲異常,并對(duì)不同的異常進(jìn)行相應(yīng)的處理。

C++中的異常處理不會(huì)逐步執(zhí)行,當(dāng)一段代碼拋出一個(gè)異常時(shí),程序就會(huì)立即停止執(zhí)行代碼,而把控制轉(zhuǎn)移給異常處理程序(exceptionhandler)進(jìn)行異常處理。完成異常處理后,程序?qū)⒗^續(xù)原來的執(zhí)行路徑。該異常處理機(jī)制能夠把程序的正常處理和異常處理邏輯分開表示,使得程序的異常處理結(jié)構(gòu)清晰,通過異常集中處理的方法,解決異常處理的問題。C++語言程序設(shè)計(jì)教程第13章異常處理13.2C++的異常處理

7

異常處理機(jī)制的主體有兩大部分:異常拋出區(qū)try,異常處理區(qū)catch,二者作為一個(gè)整體出現(xiàn),構(gòu)成try-catch結(jié)構(gòu)。它們不能單獨(dú)使用,也不能在其間插入語句。如圖13-1所示。C++語言程序設(shè)計(jì)教程第13章異常處理13.2C++的異常處理

8

異常類型可以是基本數(shù)據(jù)類型、構(gòu)造數(shù)據(jù)類型,還可以是類類型,類型名后可以帶變量名(對(duì)象),這樣就可以像函數(shù)的參數(shù)傳遞一樣將異常類型表達(dá)式的值傳入。異常類型為…表示可以捕獲任意類型的異常,但catch(…)不能出現(xiàn)在其他捕獲語句之前,否則出現(xiàn)編譯錯(cuò)誤。

異常處理的執(zhí)行過程如下:

(1)

執(zhí)行try塊中的程序語句序列;

(2)

如果執(zhí)行期間沒有執(zhí)行到throw()(沒有引起異常),跳過異常處理區(qū)的catch語句塊,程序向下執(zhí)行;

(3)若執(zhí)行期間引起異常,執(zhí)行throw()語句拋出異常,進(jìn)入異常處理區(qū),將throw()拋出的異常類型表達(dá)式(對(duì)象)依次與catch()中的類型匹配,獲得匹配的catch子句將捕獲并處理異常。繼續(xù)執(zhí)行異常處理區(qū)后的語句;

(4)

如果未找到匹配(異常未捕獲到),自動(dòng)調(diào)用結(jié)束函數(shù)terminate(),其缺省功能是調(diào)用abort()終止程序。C++語言程序設(shè)計(jì)教程第13章異常處理13.2C++的異常處理

注意:

在VC++6.0環(huán)境中,要使用異常處理機(jī)制需進(jìn)行如下設(shè)置:

Project→Settings…→在Category中選C++Language→選擇EnableExceptionHandling9

2.鏈表類模板C++語言程序設(shè)計(jì)教程第13章異常處理123456789101112131415161720212324252627/*****************************************************程序名:p13_1.cpp**功能:帶異常處理的求兩個(gè)數(shù)的商*****************************************************/#include<iostream>usingnamespacestd;floatquotient(inta,intb)throw(char*){if(b==0)//捕獲異常

throw("Divide0!");else returna/(float)b;}intmain(){ inta,b; cout<<"Inputa,b:"; cin>>a>>b;

try {cout<<a<<"/"<<b<<"="<<quotient(a,b);}

catch(char*ErrS) {cerr<<ErrS<<endl; }return0;}運(yùn)行結(jié)果:Inputa,b:13↙

1/3=0.333333

Inputa,b,:30↙

Divide0!

10

有時(shí),程序員會(huì)在一個(gè)帶異常處理的函數(shù)中調(diào)用另一個(gè)函數(shù),而在另一個(gè)函數(shù)中,也可能產(chǎn)生異常。這樣通過函數(shù)嵌套調(diào)用形成了異常處理嵌套。在這種情況下,最底層函數(shù)所拋出的異常首先在內(nèi)層catch語句序列中依次查找與之匹配的處理,如果內(nèi)層不能捕獲,則內(nèi)層函數(shù)拋出的異常逐層向外傳遞,最后回到主程序中。所以,不論調(diào)用了幾層函數(shù),只要在try區(qū)塊中調(diào)用,這些函數(shù)拋出的異常,都可以捕獲,并可以集中在主程序中處理。C++語言程序設(shè)計(jì)教程第13章異常處理13.3異常處理嵌套與重拋異常

11

2.鏈表類模板C++語言程序設(shè)計(jì)教程第13章異常處理123456789101112131415161718192021/*************************************************************程序名:p13_2.cpp**功能:帶異常處理嵌套的求二元一次方程的解*************************************************************/#include<cmath>#include<iostream>usingnamespacestd;structRes{ floatx1,x2;};Resresolution(inta,intb,intc)throw(int);intmain(){ inta,b,c; Resr; cout<<"Inputa,b,c:"; cin>>a>>b>>c;

try//異常偵測區(qū)

{ r=resolution(a,b,c); cout<<"x1="<<r.x1<<"\tx2="<<r.x2<<endl; }12

2.鏈表類模板C++語言程序設(shè)計(jì)教程第13章異常處理2223242526272829303132333435363738394041catch(int) { cerr<<"SqrtNegativeException"<<endl; } catch(...) { cerr<<"unexpectedorrethrowexception!"<<endl; }return0;}floatquotient(inta,intb)throw(char*){if(b==0)//捕獲異常

throw("Divide0!");else returna/(float)b;}Resresolution(inta,intb,intc){Restmpr;13

2.鏈表類模板C++語言程序設(shè)計(jì)教程第13章異常處理4243444546474849505152535455565758596061try{if(a==0&&b!=0) { tmpr.x1=tmpr.x2=quotient(c,b); returntmpr; }if(b*b-4*a*c<0) throw(b);tmpr.x1=quotient(-b+sqrt(b*b-4.0*a*c),2*a);tmpr.x2=quotient(-b-sqrt(b*b-4.0*a*c),2*a);returntmpr;}

catch(char*ErrS){ cerr<<ErrS<<endl; //exit(0); //throw;}}運(yùn)行結(jié)果:Inputa,b,c:123↙

SqrtNegativeException!

Inputa,b,c:003↙

Divide0!

x1=5.88749e-039,x2=1.8347e-039

Inputa,b,c:1-32↙

x1=2x2=1

14C++提供了標(biāo)準(zhǔn)異常處理類庫,它用來拋出C++標(biāo)準(zhǔn)庫中函數(shù)執(zhí)行時(shí)的異常。C++標(biāo)準(zhǔn)異常處理類的層次結(jié)構(gòu)圖如下圖所示:C++語言程序設(shè)計(jì)教程第13章異常處理流13.4標(biāo)準(zhǔn)異常類

15

2.鏈表類模板C++語言程序設(shè)計(jì)教程第13章異常處理1234567891011121314151617181920/*****************************************************程序名:p13_3.cp**功能:標(biāo)準(zhǔn)異常類的使用*****************************************************/#include<iostream>//#include<new>//在VisualC++6.0中可以不包含#include<string>//#include<stdexcept>//在VisualC++6.0中可以不包含usingnamespacestd;intmain(){ string*S;

try

{ S=newstring("ABCD");//可能拋出bad_alloc異常

cout<<S->substr(5,2);//可能拋出out_of_range異常

}

catch(bad_alloc&NoMemory) { cout<<"Exceptionoccurred:"<

溫馨提示

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

評(píng)論

0/150

提交評(píng)論