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

下載本文檔

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

文檔簡介

C++面向?qū)ο蟪绦蛟O(shè)計(jì)第10章異常處理2023/2/51燕京理工學(xué)院第10章異常處理本章學(xué)習(xí)要點(diǎn)一個(gè)好的程序不僅要保證能實(shí)現(xiàn)所需要的功能,而且還應(yīng)該有很好的容錯(cuò)能力。在程序運(yùn)行過程中如果有異常情況出現(xiàn),程序本身應(yīng)該能解決這些異常,而不是死機(jī)。本章介紹異常處理的基本概念、C++異常處理語句、析構(gòu)函數(shù)與異常處理。通過本章的學(xué)習(xí),掌握了C++異常處理的機(jī)制,我們就可以在編制程序時(shí)靈活地加以運(yùn)用,從而使我們編制的程序在遇到異常情況時(shí)能擺脫大的影響,避免出現(xiàn)死機(jī)等現(xiàn)象。2023/2/52燕京理工學(xué)院第10章異常處理10.1C++異常處理概述10.2C++異常處理的實(shí)現(xiàn)10.3異常與函數(shù)10.4異常與類10.5圖書館圖書借閱管理系統(tǒng)中的異常處理2023/2/53燕京理工學(xué)院10.1C++異常處理概述程序中常見的錯(cuò)誤有兩大類:語法錯(cuò)誤和運(yùn)行錯(cuò)誤。在編譯時(shí),編譯系統(tǒng)能發(fā)現(xiàn)程序中的語法錯(cuò)誤(如關(guān)鍵字拼寫錯(cuò)誤,變量名未定義,語句末尾缺分號(hào),括號(hào)不配對等),程序員通過錯(cuò)誤提示可以進(jìn)行修改。2023/2/54燕京理工學(xué)院有的程序雖然能通過編譯,也能投入運(yùn)行,但是在運(yùn)行過程中會(huì)出現(xiàn)異常,得不到正確的運(yùn)行結(jié)果,甚至導(dǎo)致程序不正常終止或出現(xiàn)死機(jī)現(xiàn)象,這些都說明程序中存在運(yùn)行錯(cuò)誤。運(yùn)行錯(cuò)誤相對來說比較隱蔽,是程序調(diào)試中的一個(gè)難點(diǎn),該錯(cuò)誤又可分為邏輯錯(cuò)誤和運(yùn)行異常兩類。邏輯錯(cuò)誤是由設(shè)計(jì)不當(dāng)造成的,如對算法理解有誤、在一系列計(jì)算過程中出現(xiàn)除數(shù)為0、數(shù)組的下標(biāo)溢出等。這些錯(cuò)誤只要我們在編程時(shí)多加留意是可以避免的。但是,運(yùn)行異常是由系統(tǒng)運(yùn)行環(huán)境造成的,導(dǎo)致程序中內(nèi)存分配、文件操作及設(shè)備訪問等操作的失敗,可能會(huì)造成系統(tǒng)運(yùn)行失常并癱瘓。10.1異常處理的概念及C++異常處理的基本思想2023/2/55燕京理工學(xué)院在運(yùn)行沒有異常處理的程序時(shí),如果運(yùn)行情況出現(xiàn)異常,由于程序本身不能處理,程序只能終止運(yùn)行。如果在程序中設(shè)置了異常處理,則在運(yùn)行情況出現(xiàn)異常時(shí),由于程序本身已設(shè)定了處理的方法,于是程序的流程就轉(zhuǎn)到異常處理代碼段處理。需要說明的是:只要程序運(yùn)行時(shí)出現(xiàn)與人們期望的情況不同,都可以認(rèn)為是異常,并對它進(jìn)行異常處理。因此,所謂異常處理是指對程序運(yùn)行時(shí)出現(xiàn)的差錯(cuò)以及其他例外情況的處理。10.1異常處理的概念及C++異常處理的基本思想2023/2/56燕京理工學(xué)院10.2異常處理的實(shí)現(xiàn)1.異常處理語句C++處理異常的機(jī)制由3個(gè)部分組成:檢查(try)、拋出(throw)和捕捉(catch)。把需要檢查的語句放在try塊中,throw用來當(dāng)出現(xiàn)異常時(shí)拋出一個(gè)異常信息,而catch則用來捕捉異常信息,如果捕捉到了異常信息,就處理它。try-throw-catch構(gòu)成了C++異常處理的基本結(jié)構(gòu)。2023/2/57燕京理工學(xué)院10.2異常處理的實(shí)現(xiàn)1.異常處理語句try-throw-catch結(jié)構(gòu)形式如下:try{…if(表達(dá)式1)throwx1…if(表達(dá)式2)throwx2…if(表達(dá)式n)throwxn…}catch(異常類型聲明1){異常處理語句序列}catch(異常類型聲明2){異常處理語句序列}…catch(異常類型聲明n){異常處理語句序列}2023/2/58燕京理工學(xué)院在try-throw-catch結(jié)構(gòu)中,try語句塊內(nèi)為需要受保護(hù)的待檢測異常的語句序列,如果懷疑某段程序代碼在執(zhí)行時(shí)有可能發(fā)生異常,就將它放入try語句塊中。當(dāng)這段代碼的執(zhí)行出現(xiàn)異常時(shí),即某個(gè)if語句中的表達(dá)式的值為真時(shí),會(huì)用其中的throw語句來拋擲這個(gè)異常。10.2異常處理的實(shí)現(xiàn)2023/2/59燕京理工學(xué)院throw語句語法:throw表達(dá)式;throw語句是在程序執(zhí)行發(fā)生了異常時(shí)用來拋擲這個(gè)異常的,其中表達(dá)式的值可以是int、float、字符串、類類型等,把異常拋擲給相應(yīng)的處理者,即類型匹配的catch語句塊。如果程序中有多處需要拋擲異常,應(yīng)該用不同類型的操作數(shù)來互相區(qū)別。throw拋出的異常,通常是被catch語句捕獲。10.2異常處理的實(shí)現(xiàn)2023/2/510燕京理工學(xué)院catch語句塊是緊跟在try語句塊后面的,即try塊和catch塊作為一個(gè)整體出現(xiàn),catch塊是try-catch結(jié)構(gòu)中的一部分,必須緊跟在try塊之后,不能單獨(dú)使用,在二者之間也不能插入其他語句。但是在一個(gè)try-catch結(jié)構(gòu)中,可以只有try塊而無catch塊。即在本函數(shù)中只檢查而不處理,把catch塊放在其他函數(shù)中。一個(gè)try-catch結(jié)構(gòu)中只能有一個(gè)try塊,但卻可以有多個(gè)catch塊,以便與不同類型的異常信息匹配。在執(zhí)行try塊中的語句時(shí)如果出現(xiàn)異常執(zhí)行了throw語句,系統(tǒng)會(huì)根據(jù)throw拋出的異常信息類型按catch塊出現(xiàn)的次序,依次檢查每個(gè)catch參數(shù)表中的異常聲明類型與拋擲的異常信息類型是否匹配,當(dāng)匹配時(shí),該catch塊就捕獲這個(gè)異常,執(zhí)行catch塊中的異常處理語句來處理該異常。10.2異常處理的實(shí)現(xiàn)2023/2/511燕京理工學(xué)院在catch參數(shù)表中,一般只寫異常信息的類型名,如:catch(double)。系統(tǒng)只檢查所拋擲的異常信息類型是否與catch參數(shù)表中的異常聲明類型相匹配,而不檢查它們的值。假如變量a,b,c都是int型,即使它們的值不同,在throw語句中寫throwa、throwb或throwc的作用也均是相同的。因此,如果需要檢測多個(gè)不同的異常信息,應(yīng)當(dāng)由throw拋出不同類型的異常信息。10.2異常處理的實(shí)現(xiàn)2023/2/512燕京理工學(xué)院異常信息類型可以是C++系統(tǒng)預(yù)定義的標(biāo)準(zhǔn)類型,也可以是用戶自定義的類型(如結(jié)構(gòu)體或類)。如果由throw拋出的異常信息屬于該類型或其子類型,則catch與throw二者匹配,catch捕獲該異常信息。注意:系統(tǒng)在檢查異常信息數(shù)據(jù)類型的匹配時(shí),不會(huì)進(jìn)行數(shù)據(jù)類型的默認(rèn)轉(zhuǎn)換,只有與所拋擲的異常信息類型精確匹配的catch塊才會(huì)捕獲這個(gè)異常。10.2異常處理的實(shí)現(xiàn)2023/2/513燕京理工學(xué)院在catch參數(shù)表中,除了指定異常信息的類型名外,還可以指定變量名,如:catch(doubled)。此時(shí),如果throw拋出的異常信息是double型的變量a,則catch在捕獲異常信息a的同時(shí),還使d獲得a的值。如果我們希望在捕獲異常信息時(shí),還能利用throw拋出的異常信息的值,這時(shí)就需要在catch參數(shù)表中寫出變量名。如:catch(doubled){cout<<"throw"<<d;}這時(shí)會(huì)輸出d的值(也就是a值)。10.2異常處理的實(shí)現(xiàn)2023/2/514燕京理工學(xué)院當(dāng)拋出的是類對象時(shí),有時(shí)希望在catch塊中顯示該對象中的某些信息?!纠?0-1】求解一元二次方程ax2+bx+c=0。其一般解為,但若a=0或b2-4ac<0時(shí),用此公式計(jì)算會(huì)出錯(cuò)。編程序,從鍵盤輸入a,b,c的值,求x1和x2。如果a=0或b2-4ac<0,輸出出錯(cuò)信息。

程序代碼參見教材P31710.2異常處理的實(shí)現(xiàn)2023/2/515燕京理工學(xué)院現(xiàn)在結(jié)合程序分析異常處理的進(jìn)行情況。(1)首先在try后面的花括號(hào)中放置上可能出現(xiàn)異常的語句塊或程序段。(2)程序運(yùn)行時(shí)將按正常的順序執(zhí)行到try塊,執(zhí)行try塊中花括號(hào)內(nèi)的語句。如果在執(zhí)行try塊內(nèi)的語句過程中沒有發(fā)生異常,則忽略所有的catch塊,流程轉(zhuǎn)到catch塊后面的語句繼續(xù)執(zhí)行。如【例10-1】運(yùn)行情況的第①種情況。10.2異常處理的實(shí)現(xiàn)2023/2/516燕京理工學(xué)院(3)如果在執(zhí)行try塊內(nèi)的語句過程中發(fā)生異常,則由throw語句拋出一個(gè)異常信息。throw語句拋出什么樣的異常由程序設(shè)計(jì)者自定,可以是任何類型的異常,在【例10-1】中拋出了整型和字符串類型的異常。10.2異常處理的實(shí)現(xiàn)2023/2/517燕京理工學(xué)院(4)這個(gè)異常信息提供給try-catch結(jié)構(gòu),系統(tǒng)會(huì)尋找與之匹配的catch塊。如果某個(gè)catch參數(shù)表中的異常聲明類型與拋擲的異常類型相匹配,該catch塊就捕獲這個(gè)異常,執(zhí)行catch塊中的異常處理語句來處理該異常。只要有一個(gè)catch塊捕獲了異常,其余的catch塊都將被忽略。如【例10-1】運(yùn)行情況的第②種情況,由try塊內(nèi)的throw語句拋擲一個(gè)整型異常,被第一個(gè)catch塊捕獲。【例10-1】運(yùn)行情況的第③種情況,由try塊內(nèi)的throw語句拋擲一個(gè)字符串類型異常,被第二個(gè)catch塊捕獲。10.2異常處理的實(shí)現(xiàn)2023/2/518燕京理工學(xué)院當(dāng)然,異常類型可以聲明為省略號(hào)(…),表示可以處理任何類型的異常。需要說明的是,catch(…)語句塊應(yīng)該放在最后面,因?yàn)槿绻旁谇懊?,它可以用來捕獲任何異常,那么后面其他的catch語句塊就不會(huì)被檢查和執(zhí)行了。(5)在進(jìn)行異常處理后,程序并不會(huì)自動(dòng)終止,繼續(xù)執(zhí)行catch塊后面的語句。10.2異常處理的實(shí)現(xiàn)2023/2/519燕京理工學(xué)院(6)如果throw拋擲的異常信息找不到與之匹配的catch塊,則系統(tǒng)就會(huì)調(diào)用一個(gè)系統(tǒng)函數(shù)terminate,在屏幕上顯示“abnormalprogramtermination”,并終止程序的運(yùn)行。10.2異常處理的實(shí)現(xiàn)2023/2/520燕京理工學(xué)院(7)拋擲異常信息的throw語句可以與try-catch結(jié)構(gòu)出現(xiàn)在同一個(gè)函數(shù)中,也可以不出現(xiàn)在同一函數(shù)中。在這種情況下,當(dāng)throw拋出異常信息后,首先在本函數(shù)中尋找與之匹配的catch塊,如果在本函數(shù)中無try-catch結(jié)構(gòu)或找不到與之匹配的catch塊,就轉(zhuǎn)到離開出現(xiàn)異常最近的try-catch結(jié)構(gòu)去處理。上面【例10-1】的程序可以修改為教材P319的代碼。10.2異常處理的實(shí)現(xiàn)2023/2/521燕京理工學(xué)院(8)異常處理還可以應(yīng)用在函數(shù)嵌套的情況下。下面以教材P320【例10-2】為例觀察在函數(shù)嵌套情況下異常檢測的處理情況,了解程序執(zhí)行順序。10.2異常處理的實(shí)現(xiàn)2023/2/522燕京理工學(xué)院2.try塊的嵌套異常處理語句在一個(gè)try塊中可以嵌套另一個(gè)try塊。每個(gè)try塊都有自己的一組catch塊,來處理在該try塊中拋出的異常。try塊的catch塊只能處理在該try塊中拋出的異常。如:try//外層的try語句{…try//內(nèi)層的try語句

{…}catch(elemtypea)//這個(gè)catch語句捕獲在內(nèi)層try塊中拋出的異常

{…}…}catch(elemtypeb)//這個(gè)catch語句捕獲在外層try塊中拋出的異常和在內(nèi)層try塊中未捕獲的異常{…}10.2異常處理的實(shí)現(xiàn)2023/2/523燕京理工學(xué)院10.3.1在函數(shù)中處理異常異常處理可以局部化為一個(gè)函數(shù),當(dāng)每次進(jìn)行該函數(shù)的調(diào)用時(shí),異常將被重置。這樣編寫程序能夠簡單明了,避免重復(fù),請看下面的例10-3。【例10-3】check是一個(gè)檢測成績異常的函數(shù),當(dāng)成績達(dá)到100分以上或低于60產(chǎn)生異常,在60和100之間的為正常成績。10.3異常與函數(shù)2023/2/524燕京理工學(xué)院10.3異常與函數(shù)#include<iostream>usingnamespacestd;voidcheck(intscore){try{

if(score>100)throw"成績超高!";elseif(score<60)throw"成績不及格!";elsecout<<"thescoreisOK..."<<score<<endl;}

catch(char*s){cout<<s<<endl;}}intmain(){check(45);check(90);check(101);

system("pause")

;return0;}2023/2/525燕京理工學(xué)院10.3.2在函數(shù)調(diào)用中完成異常處理在處理異常檢測時(shí),也可以將拋擲異常的程序代碼放在一個(gè)函數(shù)中,將檢測處理異常的函數(shù)代碼放在另一個(gè)函數(shù)中,能讓異常處理更具靈活性和實(shí)用性,如例10-4所示。【例10-4】異常處理從函數(shù)中獨(dú)立出來,由調(diào)用函數(shù)完成。10.3異常與函數(shù)2023/2/526燕京理工學(xué)院10.3異常與函數(shù)#include<iostream>usingnamespacestd;voidcheck(intscore){

if(score>100)throw"成績超高!";elseif(score<60)throw"成績不及格!";elsecout<<"thescoreisOK..."<<score<<endl;}intmain(){try{check(45);}

catch(char*s){cout<<s<<endl;}try{check(90);}

catch(char*s){cout<<s<<endl;}try{check(101);}

catch(char*s){cout<<s<<endl;}

system("pause")

;return0;}2023/2/527燕京理工學(xué)院10.3.3限制函數(shù)異常為便于閱讀程序,使用戶在看程序時(shí)能夠知道所用的函數(shù)是否會(huì)拋出異常信息以及拋出的異常信息的類型,C++允許在函數(shù)聲明時(shí)指定函數(shù)拋出的異常信息的類型,如:doubleDeta(double,double,double)throw(double);表示Deta函數(shù)只能拋出double類型的異常信息。如果寫成:doubleDeta(double,double,double)throw(int,float,double,char);則表示Deta函數(shù)可以拋出int、float、double或char類型的異常信息。10.3異常與函數(shù)2023/2/528燕京理工學(xué)院10.3.3限制函數(shù)異常異常指定是函數(shù)聲明的一部分,必須同時(shí)出現(xiàn)在函數(shù)聲明和函數(shù)定義的首行中,否則編譯時(shí),編譯系統(tǒng)會(huì)報(bào)告“類型不匹配”。如果在函數(shù)聲明時(shí)不指定函數(shù)拋出的異常信息的類型,則該函數(shù)可以拋出任何類型的異常。如:intFunc(int,char);//函數(shù)Func可以拋出任何異常如果在函數(shù)聲明時(shí)指定throw參數(shù)表為不包括任何類型的空表,則不允許函數(shù)拋出任何異常。如:intFunc(int,char)throw();

//不允許函數(shù)Func拋出任何異常這時(shí)即使在函數(shù)中出現(xiàn)了throw語句,實(shí)際上在函數(shù)執(zhí)行出現(xiàn)異常時(shí)也并不執(zhí)行throw語句,并不拋出任何異常信息,程序?qū)⒎钦=K止。10.3異常與函數(shù)2023/2/529燕京理工學(xué)院10.4.1構(gòu)造函數(shù)、析構(gòu)函數(shù)與異常處理構(gòu)造函數(shù)是一個(gè)特殊的函數(shù),對象創(chuàng)建時(shí),構(gòu)造函數(shù)自動(dòng)被調(diào)用。如果構(gòu)造函數(shù)中出現(xiàn)了問題,拋出了異常,會(huì)發(fā)生什么情況?請看下面的例10-5?!纠?0-5】類Number的私有數(shù)據(jù)成員i賦值空間是小于等于100的數(shù),如果賦值大于100會(huì)產(chǎn)生異常。10.4異常與類2023/2/530燕京理工學(xué)院10.4異常與類#include<iostream>usingnamespacestd;classNumber{public:

Number(inti){cout<<"inNumberconstructor..."<<endl;

if(i>100)throwi;elsenumber=i;}~Number(){cout<<"inNumberdestructor..."<<endl;}private:

intnumber;};intmain(){try{Numberobj(111);}

catch(inte){cout<<"catchanexceptionwhenallocatedNumber"<<e<<endl;}

cout<<"intheend"<<endl;

system("pause")

;return0;}2023/2/531燕京理工學(xué)院10.4.1構(gòu)造函數(shù)、析構(gòu)函數(shù)與異常處理C++異常處理的強(qiáng)大功能,不僅在于它能夠處理各種不同類型的異常,還在于它具有為異常拋出前已構(gòu)造的所有局部對象自動(dòng)調(diào)用析構(gòu)函數(shù)的能力。10.4異常與類2023/2/532燕京理工學(xué)院10.4.2異常類1.關(guān)于異常類用來傳遞異常信息的類就是異常類。異常類可以非常簡單,甚至沒有任何成員;也可以同普通類一樣復(fù)雜,有自己的數(shù)據(jù)成員、成員函數(shù)、構(gòu)造函數(shù)、析構(gòu)函數(shù)、虛函數(shù)等,還可以通過派生方式構(gòu)成異常類的繼承層次結(jié)構(gòu)。下面我們首先看例10-6,程序中聲明了一個(gè)沒有任何成員的簡單異常類。例10-7程序中聲明了一個(gè)同普通類一樣的有數(shù)據(jù)成員和成員函數(shù)的較復(fù)雜的異常類。10.4異常與類2023/2/533燕京理工學(xué)院10.4.2異常類1.關(guān)于異常類【例10-6】設(shè)計(jì)一個(gè)堆棧,當(dāng)入棧元素超出了堆棧容量時(shí),就拋出一個(gè)棧滿的異常。10.4異常與類2023/2/534燕京理工學(xué)院#include<iostream>usingnamespacestd;constintMAX=3;classFull{}; //堆棧滿時(shí)拋出的異常類classEmpty{};//堆??諘r(shí)拋出的異常類classStack{public:

Stack(){top=-1;}voidpush(inta);

intpop();private:

int

s[MAX];

inttop;};2023/2/535燕京理工學(xué)院voidStack::push(inta){

if(top>=MAX-1)throwFull();

s[++top]=a;}int

Stack::pop(){

if(top<0)throwEmpty();returns[top--];}2023/2/536燕京理工學(xué)院intmain(){Stacks;try{s.push(1);s.push(2);s.push(3);s.push(4); //將產(chǎn)生棧滿異常

cout<<"s[0]="<<s.pop()<<endl;

cout<<"s[1]="<<s.pop()<<endl;

cout<<"s[2]="<<s.pop()<<endl;//cout<<"s[3]="<<s.pop()<<endl;//將產(chǎn)生??债惓catch(Full){cout<<"Exception:StackFull!"<<endl;}catch(Empty){cout<<"Exception:StackEmpty!"<<endl;}system("pause")

;return0;}2023/2/537燕京理工學(xué)院10.4.2異常類2.異常對象由異常類建立的對象稱為異常對象。異常類的處理過程實(shí)際上就是異常對象的生成與傳遞過程。在編寫程序時(shí),如果發(fā)生異常,可以拋擲一個(gè)異常類對象,在catch語句中,可以輸出這個(gè)異常類對象的相關(guān)信息。10.4異常與類2023/2/538燕京理工學(xué)院10.4.2異常類2.異常對象例10-7修改例10-6的Full異常類,修改后的Full類具有構(gòu)造函數(shù)和成員函數(shù)getValue,還有一個(gè)數(shù)據(jù)成員a。利用這些成員,可以獲取異常發(fā)生時(shí)沒有入棧的元素信息。10.4異常與類2023/2/539燕京理工學(xué)院#include<iostream>usingnamespacestd;constintMAX=3;classFull{public:

Full(int

i):a(i){}

int

getValue(){returna;}private:

inta;};classEmpty{};2023/2/540燕京理工學(xué)院classStack{public:

Stack(){top=-1;}voidpush(inta){

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(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ǔ)空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論