C++.NET面向?qū)ο蟪绦蛟O(shè)計CH8_第1頁
C++.NET面向?qū)ο蟪绦蛟O(shè)計CH8_第2頁
C++.NET面向?qū)ο蟪绦蛟O(shè)計CH8_第3頁
C++.NET面向?qū)ο蟪绦蛟O(shè)計CH8_第4頁
C++.NET面向?qū)ο蟪绦蛟O(shè)計CH8_第5頁
已閱讀5頁,還剩34頁未讀, 繼續(xù)免費閱讀

下載本文檔

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

文檔簡介

第8章異常C++的異常處理機制能將異常檢測與異常處理分離開來,當異常發(fā)生時能自動調(diào)用異常處理程序進行錯誤處理。異常處理機制增加了程序的清晰性和可讀性,使程序員能夠編寫出清晰、健壯、容錯能力更強的程序,適用于大型軟件開發(fā)。本章主要介紹C++異常處理的語言機制,包括異常的結(jié)構(gòu)、捕捉和處理,以及異常類。8.1異常處理概述商業(yè)軟件常會提供許多錯誤處理代碼,以便對各種可能出現(xiàn)錯誤的程序代碼進行檢測和處理,增加程序的健壯性。處理程序錯誤的代碼可能出現(xiàn)在源碼的任何地方,比如判定new是否成功分配內(nèi)存、數(shù)據(jù)下標是否越界、運算溢出、除數(shù)0、無效參數(shù)等。錯誤處理代碼“污染”了程序源碼、大量的錯誤處理代碼使原本簡單的程序變得晦澀難懂。8.1異常處理概述2、傳統(tǒng)的異常處理方法傳統(tǒng)程序處理異常的典型方法是不斷測試程序繼續(xù)運行的必要條件,并對測試結(jié)果進行處理。形式如下偽碼所示:執(zhí)行任務(wù)1if任務(wù)1未能被正確執(zhí)行執(zhí)行錯誤處理程序執(zhí)行任務(wù)2if任務(wù)2未能正確執(zhí)行執(zhí)行錯誤處理程序執(zhí)行任務(wù)3

缺點錯誤處理代碼分布在整個程序的各個部分,使程序受到了錯誤處理代碼的“污染”。8.1異常處理概述3、C++異常處理思想其基本思想是將異常發(fā)生和異常處理分別放在不同的函數(shù)中,產(chǎn)生異常的函數(shù)不需要具備處理異常的能力。當一個函數(shù)出現(xiàn)異常時,它可以拋出一個異常,然后由該函數(shù)的調(diào)用者捕獲并處理這個異常,如果調(diào)用者不能處理,它可以將該異常拋給其上一級的調(diào)用者處理。8.1異常處理概述4、C++的異常處理的作用改善程序的可讀性和可維護性,將異常處理代碼與主程序代碼分離,適合團隊開發(fā)大型項目。有力的異常檢測和可能的異常恢復(fù),以統(tǒng)一方式處理異常。在異常引起系統(tǒng)錯誤之前處理異常。處理由庫函數(shù)引起的異常。在出現(xiàn)無法處理的異常時執(zhí)行清理工作,并以適當?shù)姆绞酵顺龀绦?。在動態(tài)調(diào)用鏈中有序地傳播異常處理。8.2異常處理基礎(chǔ)8.2.1異常處理的結(jié)構(gòu)try{…… //try程序塊

iferr1throwxx1……iferr2throwxx2……iferrnthrow

xxn}catch(type1arg){……} //異常類型1錯誤處理catch(type2arg){……} //異常類型2錯誤處理catch(typem

arg){……}//異常類型m錯誤處理……8.2異常處理基礎(chǔ)8.2.1異常處理的結(jié)構(gòu)try{…… //try程序塊

iferr1throwxx1……iferr2throwxx2……iferrnthrow

xxn}catch(type1arg){……} //異常類型1錯誤處理catch(type2arg){……} //異常類型2錯誤處理catch(typem

arg){……}//異常類型m錯誤處理……8.2異常處理基礎(chǔ)8.2.1異常處理的結(jié)構(gòu)try{…… //try程序塊

iferr1throwxx1……iferr2throwxx2……iferrnthrow

xxn}catch(type1arg){……} //異常類型1錯誤處理catch(type2arg){……} //異常類型2錯誤處理catch(typem

arg){……}//異常類型m錯誤處理……8.2異常處理基礎(chǔ)try-throw-catch異常處理的執(zhí)行邏輯如下1、當程序執(zhí)行過程中遇到try塊時,將進入try塊并按正常的程序邏輯順序執(zhí)行其中的語句2、如果try塊的所有語句都被正常執(zhí)行,沒有發(fā)生任何異常,那么try塊中就不會有異常被throw。在這種情況下,程序?qū)⒑雎运械腸atch塊,順序執(zhí)行那些不屬于任何catch塊的程序語句,并按正常邏輯結(jié)束程序的執(zhí)行,就像catch塊不存在一樣。8.2異常處理基礎(chǔ)3、如果在執(zhí)行try塊的過程中,某條語句產(chǎn)生錯誤并用throw拋出了異常,則程序控制流程將自此throw子句轉(zhuǎn)移到catch塊,try塊中該throw語句之后的所有語句都不會再被執(zhí)行了。4、C++將按catch塊出現(xiàn)的次序,用異常的數(shù)據(jù)類型與每個catch參數(shù)表中指定的數(shù)據(jù)類型相比較,如果兩者類型相同,就執(zhí)行該catch塊,同時還將把異常的值傳遞給catch塊中的形參arg(如果該塊有arg形參)。只要有一個catch塊捕獲了異常,其余catch塊都將被忽略。5、如果沒有任何catch能夠匹配該異常,C++將調(diào)用系統(tǒng)默認的異常處理程序處理該異常,其通常做法是直接終止該程序的運行?!纠?-1】異常處理的簡單例程。//CH8-1.cpp#include<iostream>usingnamespacestd;voidmain(){

cout<<"1--befroetryblock..."<<endl;try{

cout<<"2--Insidetryblock..."<<endl;throw10;

cout<<"3--Afterthrow...."<<endl;}

catch(inti){

cout<<"4--Incatchblock1...exception..errcodeis.."<<i<<endl;}

catch(char*s){

cout<<"5--Incatchblock2...exception..errcodeis.."<<s<<endl;}

cout<<"6--AfterCatch...";}8.2.2異常捕獲異常捕獲由catch完成,catch必須緊跟在與之對應(yīng)的try塊后面。如果異常被某catch捕獲,程序?qū)?zhí)行該catch塊中的代碼,之后將繼續(xù)執(zhí)行catch塊后面的語句;如果異常不能被任何catch塊捕獲,它將被傳遞給系統(tǒng)的異常處理模塊,程序?qū)⒈幌到y(tǒng)異常處理模塊終止。catch根據(jù)異常的數(shù)據(jù)類型捕獲異常,如果catch參數(shù)表中異常聲明的數(shù)據(jù)類型與throw拋出的異常的數(shù)據(jù)類型相同,該catch塊將捕獲異常。注意:catch在進行異常數(shù)據(jù)類型的匹配時,不會進行數(shù)據(jù)類型的默認轉(zhuǎn)換,只有與異常的數(shù)據(jù)類型精確匹配的catch塊才會被執(zhí)行。8.2.2異常捕獲【例8-2】catch捕獲異常時,不會進行數(shù)據(jù)類型的默認轉(zhuǎn)換。//CH8-2.cpp#include<iostream>usingnamespacestd;voidmain(){

cout<<"1--befroetryblock..."<<endl;try{

cout<<"2--Insidetryblock..."<<endl;throw10;

cout<<"3--Afterthrow...."<<endl;}

catch(doublei){ //僅此與例8.1不同

cout<<"4--Incatchblock1..aninttypeis.."<<i<<endl;}

cout<<"5--AfterCatch...";}8.3異常與函數(shù)8.3.1在函數(shù)中處理異常異常處理可以局部化為一個函數(shù),當每次進行該函數(shù)的調(diào)用時,異常將被重置?!纠?-3】temperture是一個檢測溫度異常的函數(shù),當溫度達到冰點或沸點時產(chǎn)生異常。#include<iostream>usingnamespacestd;voidtemperature(intt){try{

if(t==100)throw"沸點!";elseif(t==0)throw"冰點!";elsecout<<"thetemperatureisOK..."<<endl;}

catch(int

x){cout<<"temperatore="<<x<<endl;}

catch(char*s){cout<<s<<endl;}}voidmain(){temperature(0); //L1temperature(10); //L2temperature(100); //L3}8.3.2在函數(shù)調(diào)用中完成異常處理將產(chǎn)生異常的程序代碼放在一個函數(shù)中,將檢測處理異常的函數(shù)代碼放在另一個函數(shù)中,能讓異常處理更具靈活性和實用性。【例8-4】異常處理從函數(shù)中獨立出來,由調(diào)用函數(shù)完成。#include<iostream>usingnamespacestd;voidtemperature(intt){

if(t==100)throw"沸點!";elseif(t==0)throw"冰點!";elsecout<<"thetemperatureis..."<<t<<endl;}voidmain(){try{temperature(10);temperature(50);temperature(100);}

catch(char*s){cout<<s<<endl;}}增補(選講)限制函數(shù)異常限制異常的方法1、當一個函數(shù)聲明中不帶任何異常描述時,它可以拋出任何異常。例如:int

f(int,char);//函數(shù)f可以拋出任何異常2、在函數(shù)聲明的后面添加一個throw參數(shù)表,在其中指定函數(shù)可以拋出的異常類型。例如:int

g(int,char)throw(int,char);

//只允許拋出int和char異常。3、指定throw限制表為不包括任何類型的空表,不允許函數(shù)拋出任何異常。如:int

h(int,char)throw();//不允許拋出任何異?!纠吭O(shè)計函數(shù)Errhandler,限制它只能拋出int、char和double類型的異常。//Eg8.cpp#include<iostream>usingnamespacestd;voidErrhandler(int

n)throw(int,char,double){

if(n==1)thrown;

if(n==2)throw'x';

if(n==3)throw1.1;}voidmain(){

cout<<"BeforeErrhander..."<<endl;try{Errhandler(1);}

catch(inti){cout<<"catchaninteger..."<<endl;}

catch(char

c){cout<<"catchanchar..."<<endl;}

catch(double

d){cout<<"catchandouble..."<<endl;}}8.4異常處理的幾種特殊情況8.4.1捕獲所有異常在多數(shù)情況下,catch都只用于捕獲某種特定類型的異常,但它也具有捕獲全部異常的能力。其形式如下:catch(…){……//異常處理代碼}【例8】改寫前面的Errhandler函數(shù),使之能夠捕獲所有異常。//CH.cpp#include<iostream>usingnamespacestd;voidErrhandler(int

n)throw(){try{

if(n==1)thrown;

if(n==2)throw"dx";

if(n==3)throw1.1;}

catch(…){cout<<"catchanexception..."<<endl;}}voidmain(){Errhandler(1);Errhandler(2);Errhandler(3);}8.4.2再次拋出異常如是catch塊無法處理捕獲的異常,它可以將該異常再次拋出,使異常能夠在恰當?shù)牡胤奖惶幚?。再次拋出的異常不會再被同一個catch塊所捕獲,它將被傳遞給外部的catch塊處理。要在catch塊中再次拋出同一異常,只需在該catch塊中添加不帶任何參數(shù)的throw語句即可?!纠?】在異常處理塊中再次拋出同一異常。//Eg8.cpp#include<iostream>usingnamespacestd;voidErrhandler(int

n)throw(){try{

if(n==1)thrown;

cout<<"allisok..."<<endl;}

catch(intn){

cout<<"catchanintexceptioninside..."<<n<<endl;

throw;//再次拋出本catch捕獲的異常

}}voidmain(){try{Errhandler(1);}

catch(intx){cout<<"catchintanexceptioninmain..."<<x<<endl;}

cout<<"....End..."<<endl;}8.4.3異常的嵌套調(diào)用try塊可以嵌套,即一個try塊中可以包括另一個try塊,這種嵌套可能形成一個異常處理的調(diào)用鏈?!纠?-5】嵌套異常處理示例。//CH8-5.cpp#include<iostream>usingnamespacestd;voidfc(){

try{throw"help...";}

catch(int

x){cout<<"

hanlder"<<endl;}

try{cout<<"noerrorhandle..."<<endl;}

catch(char*px){cout<<"infc..char*hanlder"<<endl;}}

voidfb(){

int*q=newint[10];try{

fc();

cout<<"returnformfc()"<<endl;}catch(…){delete[]q;throw;}}voidfa(){char*p=newchar[10];try{

fb();

cout<<"returnfromfb()"<<endl;}catch(…){delete[]p;throw;}}voidmain(){try{

fa();

cout<<"returnfromfa"<<endl;}catch(…){cout<<"inmain"<<endl;}

cout<<"End"<<endl;}例8-5的調(diào)用過程8.5異常和類8.5.1構(gòu)造函數(shù)與異常由于構(gòu)造函數(shù)沒有返回類型,在執(zhí)行構(gòu)造函數(shù)過程中若出現(xiàn)異常,傳統(tǒng)處理方法可能是:返回一個處于錯誤狀態(tài)的對象,外部程序可以檢查該對象狀態(tài),以便判定該對象是否被成功構(gòu)造。設(shè)置一個全局變量保存對象構(gòu)造的狀態(tài),外部程序可以通過該變量值判斷對象構(gòu)造的情況。在構(gòu)造函數(shù)中不做對象的初始化工作,而是專門設(shè)計一個成員函數(shù)負責對象的初始化。C++中異常處理機制能夠很好地處理構(gòu)造函數(shù)中的異常問題,當構(gòu)造函數(shù)出現(xiàn)錯誤時就拋出異常,外部函數(shù)可以在構(gòu)造函數(shù)之外捕獲并處理該異常。8.5異常和類【例8-6】類B有一個類A的對象成員數(shù)組obj,類B的構(gòu)造函數(shù)進行了自由存儲空間的過量申請,最后造成內(nèi)存資源耗盡產(chǎn)生

異常,則異常將調(diào)用對象成員數(shù)組obj的析構(gòu)函數(shù),回收obj占用的存儲空間。//CH8-6.cpp#include<iostream>usingnamespacestd;classA{

inta;public:

A(inti=0):a(i){}~A(){cout<<"inAdestructor..."<<endl;}};classB{Aobj[3];double*pb[10];public:

B(intk){cout<<"intBconstructor..."<<endl;for(inti=0;i<10;i++){pb[i]=newdouble[20000000];if(pb[i]==0)throwi;elsecout<<"Allocated20000000doublesinpb["<<i<<"]"<<endl;}}};voidmain(){try{Bb(2);}catch(int

e){cout<<"catchanexceptionwhenallocatedpb["<<e<<"]"<<endl;}}8.5.2異常類1、關(guān)于異常類異常可以是任何類型,包括自定義類。用來傳遞異常信息的類就是異常類。異常類可以非常簡單,甚至沒有任何成員;也可以同與普通類一樣復(fù)雜,有自己的成員函數(shù)、數(shù)據(jù)成員、構(gòu)造函數(shù)、析構(gòu)函數(shù)、虛函數(shù)等,還可以通過派生方式構(gòu)成異常類的繼承層次結(jié)構(gòu)?!纠?-7】設(shè)計一個堆棧,當入棧元素超出了堆棧容量時,就拋出一個棧滿的異常;如果棧已空還要從棧中彈出元素,就拋出一個??盏漠惓?。//CH8-7.cpp#include<iostream>usingnamespacestd;constintMAX=3;classFull{}; //L1堆棧滿時拋出的異常類classEmpty{}; //L2堆棧空時拋出的異常類classStack{private:

int

s[MAX];

inttop;public:voidpush(inta);

intpop();

Stack(){top=-1;}};voidStack::push(inta){

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

s[++top]=a;}int

Stack::pop(){

if(top<0)throwEmpty(); returns[top--];}voidmain(){Stacks;try{s.push(10);s.push(20);s.push(30);//s.push(40); //L5將產(chǎn)生棧滿異常

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

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

cout<<"stack(2)="<<s.pop()<<endl;

cout<<"stack(3)="<<s.pop()<<endl; //L6}

catch(Full){cout<<"Exception:StackFull"<<endl;}

catch(Empty){ cout<<"Exception:StackEmpty"<<endl;}}8.5.2異常類2.異常對象由異常類建立的對象稱為異常對象。異常類的處理過程實際上就是異常對象的生成與傳遞過程。如右圖【例8-8】修改例8-10的Full異常類,修改后的Full類具有構(gòu)造函數(shù)和成員函數(shù),還有一個數(shù)據(jù)成員。利用這些成員,可以獲取異常發(fā)生時沒有入棧的元素信息。//CH8-8.cpp#include<iostream>usingnamespacestd;constintMAX=3;classFull{

inta;public:

Full(int

i):a(i){}

int

getValue(){returna;}};classEmpty{};classStack{private:

int

s[MAX];

inttop;public:

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

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

s[++top]=a;}

intpop(){

if(top<0)throwEmpty();returns[top--];}};voidmain(){Stacks;try{s.push(10);s.push(20); s.push(30);s.push(40);}

catch(Fulle){

cout<<"Exception:StackFull..."<<endl;

cout<<"Thevaluenotpushinstack:“<<e.getValue()<<endl;}}8.5.3派生異常類的處理在設(shè)計軟件的異常處理系統(tǒng)時,可以將各種異常匯集起來,根據(jù)異常的性質(zhì)將其分屬到不同的類中,形成異常類的繼承體系結(jié)構(gòu)。還可以利用類的多態(tài)性,將異常類設(shè)計為具有多態(tài)特性的繼承體系,利用多態(tài)的強大功能處理異常。一個進行遠程登錄訪問程序的異常類層次結(jié)構(gòu)如圖?!纠?-9】設(shè)計圖8-3所示異常繼承體系中從BasicException到FileSysException部分的異常類。//CH8-9.cpp#include<iostream>usingnamespacestd;classBasicException{public:char*Where(){return"BasicException...";}};classFileSysException:public

BasicException{public:char*Where(){return"FileSysException...";}};classFileNotFound:public

FileSysException{public:char*Where(){retur

溫馨提示

  • 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)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論