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

下載本文檔

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

文檔簡介

第11章

異常處理11.1異常處理概述11.2異常處理的基本思想11.3異常處理的實(shí)現(xiàn)11.4標(biāo)準(zhǔn)C++庫中的異常類11.5多路捕獲11.6含有異常的程序設(shè)計11.1異常處理概述程序可能按編程者的意愿終止,也可能因?yàn)槌绦蛑邪l(fā)生了錯誤而終止。程序的錯誤有兩種,一種是編譯錯誤,即語法錯誤。如果使用了錯誤的語法、函數(shù)、結(jié)構(gòu)和類,程序就無法被生成運(yùn)行代碼。另一種是在運(yùn)行時發(fā)生的錯誤,它分為不可預(yù)料的邏輯錯誤和可以預(yù)料的運(yùn)行異常。異常處理機(jī)制是用于管理程序運(yùn)行期間錯誤的一種結(jié)構(gòu)化方法。所謂結(jié)構(gòu)化是指程序的控制不會由于產(chǎn)生異常而隨意跳轉(zhuǎn)。異常處理機(jī)制將程序中的正常處理代碼與異常處理代碼顯式區(qū)別開來,提高了程序的可讀性。

返回首頁11.2異常處理的基本思想異常的基本思想是:

(1)實(shí)際的資源分配通常在程序的低層進(jìn)行,如上圖中的F3()。(2)當(dāng)操作失敗、無法分配內(nèi)存或無法打開一個文件時,在邏輯上如何進(jìn)行處理通常在程序的高層,如上圖中的F1(),中間還可能有與用戶的對話。(3)異常為從分配資源的代碼轉(zhuǎn)向處理錯誤狀態(tài)的代碼提供了一種表達(dá)方式。如果還存在中間層次的函數(shù),如上圖中的F2(),則為它們釋放所分配的內(nèi)存提供了機(jī)會,但這并不包括傳遞錯誤狀態(tài)信息的代碼。返回首頁圖11-1異常處理示意圖返回本節(jié)11.3異常處理的實(shí)現(xiàn)11.3.1異常處理的語法11.3.2異常處理機(jī)制返回首頁C++語言異常處理機(jī)制的基本思想是將異常的檢測與處理分離。當(dāng)在一個函數(shù)體中檢測到異常條件存在,但無法確定相應(yīng)的處理方法時,將引發(fā)一個異常,并由函數(shù)的直接或間接調(diào)用檢測并處理這個異常。這一基本思想用3個保留字實(shí)現(xiàn):throw、try和catch。其作用是:(1)try:標(biāo)識程序中異常語句塊的開始。(2)throw:用來創(chuàng)建用戶自定義類型的異常錯誤。(3)catch:標(biāo)識異常錯誤處理模塊的開始。

11.3.1異常處理的語法在C++程序中,任何需要檢測異常的語句(包括函數(shù)調(diào)用)都必須在try語句塊中執(zhí)行,異常必須由緊跟在try語句后面的catch語句來捕獲并處理。因而,try與catch總是結(jié)合使用。throw、try和catch語句的一般語法如下:

throw<表達(dá)式>;try{ //try語句塊}catch(類型1參數(shù)1){ //針對類型1的異常處理}catch(類型2參數(shù)2){ //針對類型2的異常處理}…catch(類型n參數(shù)n){ //針對類型n的異常處理}try子句后的復(fù)合語句是代碼的保護(hù)段。如果預(yù)料某段程序代碼(或?qū)δ硞€函數(shù)的調(diào)用)有可能發(fā)生異常,就將它放在try子句之后。如果這段代碼(或被調(diào)函數(shù))運(yùn)行時真的遇到異常情況,其中的throw表達(dá)式就會拋擲這個異常。catch子句后的復(fù)合語句是異常處理程序,“捕獲”(處理)由throw表達(dá)式拋擲的異常。異常類型說明部分指明該子句處理的異常的類型,它與函數(shù)的形參是類似的,可以是某個類型的值,也可以是引用。

例11-1:異常處理示例程序。

#include<iostream.h>voidmain(){char*ptr;try //異常模塊{

if((ptr=newchar[64*1024])==NULL)throw"NotEnoughMemory!";}catch(char*str) //異常錯誤處理模塊{ //……錯誤處理代碼

cout<<"Exception:"<<str<<endl;}}異常處理的執(zhí)行過程如下:

(1)控制通過正常的順序執(zhí)行到達(dá)try語句,然后執(zhí)行try塊內(nèi)的保護(hù)段。(2)如果在保護(hù)段執(zhí)行期間沒有引起異常,那么跟在try塊后的catch子句就不執(zhí)行,程序從異常被拋擲的try塊后跟隨的最后一個catch子句后面的語句繼續(xù)執(zhí)行下去。(3)如果在保護(hù)段執(zhí)行期間或在保護(hù)段調(diào)用的任何函數(shù)中(直接或間接的調(diào)用)有異常被拋擲,則從通過throw運(yùn)算數(shù)創(chuàng)建的對象中創(chuàng)建一個異常對象(這隱含指可能包含一個拷貝構(gòu)造函數(shù))。

(4)如果匹配的處理器未找到,則函數(shù)terminate將被自動調(diào)用,而函數(shù)terminate的默認(rèn)功能是調(diào)用abort終止程序。(5)如果找到了一個匹配的catch處理程序,且它通過值進(jìn)行捕獲,則其形參通過拷貝異常對象進(jìn)行初始化。

例11-2:閱讀下列程序,寫出運(yùn)行結(jié)果。

#include<iostream.h>voidExcp();classEx{public: Ex(){}; ~Ex(){};};classDemo{public: Demo() //構(gòu)造函數(shù) {

cout<<"CreateingaDemoobject."<<endl; }~Demo() //析構(gòu)函數(shù) {

cout<<"DeletingDemoobject."<<endl; }};voidExcp(){DemoA; //定義一個對象

cout<<"Excpfunctionthrowinganexception!"; cout<<endl; throwEx(); //創(chuàng)建成一個異常}voidmain(){ try { cout<<"NowcallExcpfunction."<<endl; Excp(); } catch(Exa) //捕捉Ex類異常 {

cout<<"AnExexceptionoccurred."<<endl; } catch(...) {

cout<<"Someotherexceptionoccurred."; cout<<endl; }}此程序的運(yùn)行結(jié)果為:NowcallExcpfunction.CreatingaDemoobject.Excpfunctionthrowinganexception!DeletingDemoobject.AnExexceptionoccurred.返回本節(jié)11.3.2異常處理機(jī)制(1)try分程序必須出現(xiàn)在前,catch緊跟出現(xiàn)在后。catch之后的圓括號中必須含有數(shù)據(jù)類型,捕獲是利用數(shù)據(jù)類型匹配實(shí)現(xiàn)的。(2)如果程序內(nèi)有多個異常錯誤處理模塊,則當(dāng)異常錯誤發(fā)生時,系統(tǒng)自動查找與該異常錯誤類型相匹配的catch模塊,查找次序?yàn)閏atch出現(xiàn)的次序。(3)如果異常錯誤類型為C++的類,并且該類有其基類,則應(yīng)該將派生類的錯誤處理程序放在前面,基類的錯誤處理程序放在后面。(4)如果一個異常錯誤發(fā)生后,系統(tǒng)找不到一個與該錯誤類型相匹配的異常錯誤處理模塊,則調(diào)用預(yù)定義的運(yùn)行時刻終止函數(shù),默認(rèn)情況下是abort。例11-3:定義一個異常類CException,有成員函數(shù)Reason()用來顯示異常的類型,定義函數(shù)fun()觸發(fā)異常,在主函數(shù)的try模塊中調(diào)用fun(),在catch模塊中捕獲異常,觀察程序的執(zhí)行過程。#include<iostream.h>classCException{public: CException(){} ~CException(){} constchar*Reason()const{return"CException類中的異常。";}

};

voidfun(){cout<<"在子函數(shù)中觸發(fā)CException類異常"<<endl; throwCException();}

voidmain(){ cout<<"進(jìn)入主函數(shù)"<<endl; try { cout<<"在try模塊中,調(diào)用子函數(shù)"<<endl; fun(); } catch(CExceptionE) {cout<<"在catch模塊中,捕獲到CException類型異常:";

cout<<E.Reason()<<endl; } catch(char*str) { cout<<"捕獲到其他類型異常:"<<str<<endl; } cout<<"回到主函數(shù),異常已被處理。"<<endl;}程序的運(yùn)行結(jié)果為:進(jìn)入主函數(shù)在try模塊中,調(diào)用子函數(shù)在子函數(shù)中觸發(fā)CException類異常在catch模塊中,捕獲到CException類型異常:CException類中的異常。回到主函數(shù),異常已被處理。例11-4:設(shè)計一個異常Exception抽象類,在此基礎(chǔ)上派生一個OutOfMemory類響應(yīng)內(nèi)存不足,一個RangeError類響應(yīng)輸入的數(shù)不在指定的范圍內(nèi),實(shí)現(xiàn)并測試這幾個類。#include<iostream.h>

classException{public: Exception(){} virtual~Exception(){} virtualvoidPrintError()=0;};

classOutOfMemory:publicException{public: OutOfMemory(){} ~OutOfMemory(){}virtualvoidPrintError();};

voidOutOfMemory::PrintError(){ cout<<"OutofMemory!"<<endl;}

classRangeError:publicException{public: RangeError(unsignedlongnumber){BadNum=number;} ~RangeError(){}virtualvoidPrintError(); virtualunsignedlongGetNumber(){returnBadNum;} virtualvoidSetNumber(unsignedlongnumber){BadNum=number;}private: unsignedlongBadNum;};

voidRangeError::PrintError(){ cout<<"Numberoutofrange.Youused"<<GetNumber()<<"!"<<endl;}

voidfun1();unsignedint*fun2();voidfun3(unsignedint*);intmain(){ try {fun1();}

catch(Exception&theException) { theException.PrintError(); } return0;}

voidfun1(){ unsignedint*p=fun2(); fun3(p); cout<<"Thenumberis:"<<*p<<endl; deletep;}unsignedint*fun2(){ unsignedint*n=newunsignedint; if(n==0) throwOutOfMemory(); returnn;}

voidfun3(unsignedint*p){ longNumber; cout<<"Enteraninteger(0~999):"; cin>>Number;if(Number>999||Number<0) throwRangeError(Number); *p=Number;}程序運(yùn)行結(jié)果為:Enteraninteger(0~999):7↙Thenumberis:7Enteraninteger(0~999):2004↙Numberoutofrange.Youused2004!例11-5:編寫用戶自定義的終止函數(shù)。#include<iostream.h>#include<eh.h>#include<process.h>voidmyterm(){ cout<<"Thisismyterminater."<<endl; … //其他代碼

exit(-1);};intmain(){ … //其他代碼

try {set_terminate(myterm); //傳遞終止函數(shù)名 … //其他代碼

throw"Exception:……."; } catch(inti) { … //其他代碼 }

return0;}返回本節(jié)11.4標(biāo)準(zhǔn)C++庫中的異常類標(biāo)準(zhǔn)C++庫中包含9個異常類,它們可以分為運(yùn)行時異常和邏輯異常:

length_error //運(yùn)行時長度異常domain_error //運(yùn)行時域異常out_of_range_error //運(yùn)行時越界異常invalid_argument //運(yùn)行時參數(shù)異常range_error //邏輯異常,范圍異常overflow_error //邏輯異常,溢出(上)異常underflow_error //邏輯異常,溢出(下)異常返回首頁下面程序簡單說明C++異常標(biāo)準(zhǔn)類exception和logic_error的使用方法。例11-6:演示標(biāo)準(zhǔn)異常類的使用。#include<iostream.h>#include<exception.h>usingnamespacestd;voidmain{ try { exceptiontheError; //聲明一個C++標(biāo)準(zhǔn)異常類的對象

throw(theError); //拋出該異常類的對象 }catch(constexception&theError) //捕捉C++標(biāo)準(zhǔn)異常類的對象 {

cout<<theError.what()<<endl; } try { logic_errortheLogicError(“LogicError!”); //聲明一個C++標(biāo)準(zhǔn)異常類(logic_error)的對象

throw(theLogicError); //拋出該異常類對象 }

catch(constexception&theLogicError) //捕捉C++標(biāo)準(zhǔn)異常類的對象 {

cout<<theLogicError.what()<<endl; //用what成員函數(shù)顯示出錯的原因 }}返回本節(jié)11.5多路捕獲很多程序可能有若干不同種類的運(yùn)行錯誤,它們可以使用異常處理機(jī)制,每種錯誤可與一個類,一種數(shù)據(jù)類型或一個值相關(guān)。這樣,在程序中就會出現(xiàn)多路捕獲。例11-7:操作string類對象時,預(yù)設(shè)兩個異常。#include<iostream.h>#include<string.h>classString{public: String(char*,int) classyichang1//異常類1 {返回首頁public: yichang1(intj):index(j){} intindex; }; classyichang2{};//異常類2

char&operator[](intk) { if(k>=0&&k<len) returnp[k]; throwyichang1(k); }private: char*p; intlen; staticintmax;};intString::max=20;String::String(char*str,intsi){ if(si<0||si>max) throwyichang2(); p=newchar[si]; strncpy(p,str,si); len=si;}voidg(String&str){ intnum=10; for(intn=0;n<num;n++) cout<<str[n]; cout<<endl;}voidf(){ //代碼區(qū)1

try { //代碼區(qū)2

Strings("abcdefghijklmnop",10); g(s); } catch(String::yichang1r) { cerr<<"->outofrange:"<<r.index<<en

溫馨提示

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

評論

0/150

提交評論