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

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權,請進行舉報或認領

文檔簡介

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

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

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

{…}…}catch(elemtypeb)//這個catch語句捕獲在外層try塊中拋出的異常和在內(nèi)層try塊中未捕獲的異常{…}10.2異常處理的實現(xiàn)2023/2/523燕京理工學院10.3.1在函數(shù)中處理異常異常處理可以局部化為一個函數(shù),當每次進行該函數(shù)的調(diào)用時,異常將被重置。這樣編寫程序能夠簡單明了,避免重復,請看下面的例10-3?!纠?0-3】check是一個檢測成績異常的函數(shù),當成績達到100分以上或低于60產(chǎn)生異常,在60和100之間的為正常成績。10.3異常與函數(shù)2023/2/524燕京理工學院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燕京理工學院10.3.2在函數(shù)調(diào)用中完成異常處理在處理異常檢測時,也可以將拋擲異常的程序代碼放在一個函數(shù)中,將檢測處理異常的函數(shù)代碼放在另一個函數(shù)中,能讓異常處理更具靈活性和實用性,如例10-4所示?!纠?0-4】異常處理從函數(shù)中獨立出來,由調(diào)用函數(shù)完成。10.3異常與函數(shù)2023/2/526燕京理工學院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燕京理工學院10.3.3限制函數(shù)異常為便于閱讀程序,使用戶在看程序時能夠知道所用的函數(shù)是否會拋出異常信息以及拋出的異常信息的類型,C++允許在函數(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燕京理工學院10.3.3限制函數(shù)異常異常指定是函數(shù)聲明的一部分,必須同時出現(xiàn)在函數(shù)聲明和函數(shù)定義的首行中,否則編譯時,編譯系統(tǒng)會報告“類型不匹配”。如果在函數(shù)聲明時不指定函數(shù)拋出的異常信息的類型,則該函數(shù)可以拋出任何類型的異常。如:intFunc(int,char);//函數(shù)Func可以拋出任何異常如果在函數(shù)聲明時指定throw參數(shù)表為不包括任何類型的空表,則不允許函數(shù)拋出任何異常。如:intFunc(int,char)throw();

//不允許函數(shù)Func拋出任何異常這時即使在函數(shù)中出現(xiàn)了throw語句,實際上在函數(shù)執(zhí)行出現(xiàn)異常時也并不執(zhí)行throw語句,并不拋出任何異常信息,程序將非正常終止。10.3異常與函數(shù)2023/2/529燕京理工學院10.4.1構造函數(shù)、析構函數(shù)與異常處理構造函數(shù)是一個特殊的函數(shù),對象創(chuàng)建時,構造函數(shù)自動被調(diào)用。如果構造函數(shù)中出現(xiàn)了問題,拋出了異常,會發(fā)生什么情況?請看下面的例10-5?!纠?0-5】類Number的私有數(shù)據(jù)成員i賦值空間是小于等于100的數(shù),如果賦值大于100會產(chǎn)生異常。10.4異常與類2023/2/530燕京理工學院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燕京理工學院10.4.1構造函數(shù)、析構函數(shù)與異常處理C++異常處理的強大功能,不僅在于它能夠處理各種不同類型的異常,還在于它具有為異常拋出前已構造的所有局部對象自動調(diào)用析構函數(shù)的能力。10.4異常與類2023/2/532燕京理工學院10.4.2異常類1.關于異常類用來傳遞異常信息的類就是異常類。異常類可以非常簡單,甚至沒有任何成員;也可以同普通類一樣復雜,有自己的數(shù)據(jù)成員、成員函數(shù)、構造函數(shù)、析構函數(shù)、虛函數(shù)等,還可以通過派生方式構成異常類的繼承層次結構。下面我們首先看例10-6,程序中聲明了一個沒有任何成員的簡單異常類。例10-7程序中聲明了一個同普通類一樣的有數(shù)據(jù)成員和成員函數(shù)的較復雜的異常類。10.4異常與類2023/2/533燕京理工學院10.4.2異常類1.關于異常類【例10-6】設計一個堆棧,當入棧元素超出了堆棧容量時,就拋出一個棧滿的異常。10.4異常與類2023/2/534燕京理工學院#include<iostream>usingnamespacestd;constintMAX=3;classFull{}; //堆棧滿時拋出的異常類classEmpty{};//堆??諘r拋出的異常類classStack{public:

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

intpop();private:

int

s[MAX];

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

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

s[++top]=a;}int

Stack::pop(){

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

Full(int

i):a(i){}

int

getValue(){returna;}private:

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

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

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論