錢能C++程序設(shè)計教程15
,單擊此處編輯母版標(biāo)題樣式,單擊此處編輯母版文本樣式,第二層,第三層,第四層,第五層,*,*,*,C+,程序設(shè)計教程,(,第二版,),第十五章,異常,Chapter 15,Exception,清華大學(xué)出版社,錢 能,10/22/2024,1,異常是一種程序控制機制,與函數(shù)機制獨立和互補,函數(shù)是一種以棧結(jié)構(gòu)展開的上下函數(shù)銜接的程序控制系統(tǒng),異常是另一種控制結(jié)構(gòu),它依附于棧結(jié)構(gòu),卻可以同時設(shè)置多個異常類型作為網(wǎng)捕條件,從而以類型匹配在棧機制中跳躍回饋,.,異常設(shè)計目的:,棧機制是一種高度節(jié)律性控制機制,面向?qū)ο缶幊虆s要求對象之間有方向、有目的的控制傳動,從一開始,異常就是沖著改變程序控制結(jié)構(gòu),以適應(yīng)面向?qū)ο蟪绦蚋行У毓ぷ鬟@個主題,而不是僅為了進(jìn)行錯誤處理。,異常設(shè)計出來之后,卻發(fā)現(xiàn)在錯誤處理方面獲得了最大的好處,10/22/2024,2,第十五章內(nèi)容,錯誤處理的復(fù)雜性,(Error,Proccessing,Complexity),使用異常,(Using Exception),捕捉異常,(Catching Exception),異常申述,(Exception Description),異常繼承體系,(Exception Inheritance System),異常應(yīng)用,(Exception Applications),非錯誤處理,(Non-Error,Proccessing,),10/22/2024,3,1.,錯誤處理的復(fù)雜性,(Error,Proccessing,Complexity),傳統(tǒng)的錯誤處理方式:,1,遇到錯誤,終止運行,,低級粗暴,2,遇到錯誤,循調(diào)用返回給上層函數(shù)一個錯誤信息,,忽略了模塊體系,3,遇到錯誤,改變?nèi)皱e誤變量的值,并函數(shù)返回,,破壞了程序結(jié)構(gòu),4,遇到錯誤,調(diào)用事先設(shè)計好的下層錯誤處理函數(shù),,可惜錯誤往往不是自己所能解決的了的!,10/22/2024,4,程序運作實情,可以將程序運行看作是諸多模塊的工作及相互往來,一個模塊發(fā)生的錯誤,需要借助于另一個模塊進(jìn)行修復(fù),每個模塊包含一個層層調(diào)用的函數(shù)體系,發(fā)生錯誤后,如果層層函數(shù)返回,則不但動作緩慢,而且錯誤信息丟失,失去處理的針對性,發(fā)生錯誤,說明模塊服務(wù)失敗,需要在主體模塊中找說法給予必要的處理,.,不同的系統(tǒng),其主體模塊是不同的,決定了“說法”也是不同的,計算元素位置,if(vi,溢出,),說明元素不存在,if(i,=size),下標(biāo)溢出,接受外來申請,if(vi,溢出,),說明資源不足,應(yīng)用模塊,2,應(yīng)用模塊,1,向量模塊,10/22/2024,5,函數(shù)機制,本質(zhì)上是一種過程控制機制,對面向?qū)ο蟪绦騺碚f,進(jìn)行從發(fā)現(xiàn)錯誤到處理錯誤的設(shè)計,是一個超出過程控制能力的龐大控制體系,10/22/2024,6,2.,使用異常,(Using Exception),錯誤處理示意:,放棄一棵子樹,循調(diào)用鏈跳到祖先函數(shù),發(fā)現(xiàn)錯誤處,10/22/2024,7,異常處理的語法:,1,框定異常發(fā)生的可能范圍,2,定義異常處理,3,拋擲異常,int,main(int,argc,char*,argv,),ifstream,in(argv1);,try,if,(!in,),throw,string(argv1);,catch,(string,s),cout,s+File,Opening Error.n;,return,1;,for,(string,s;,getline(in,s);),cout,s“n”;,10/22/2024,8,異常擅長于在函數(shù)調(diào)用鏈中騰挪,void,f0(),throw,string(“,請?zhí)幚?n”);,void,f1()f0();,void,f2()f1();,void,f3()f2();,void,f4()f3();,void,f5()f4();,int,main(),try,f5();,catch,(string,),cout,“,處理中,n”;,10/22/2024,9,系統(tǒng)中提供了標(biāo)準(zhǔn)異常在標(biāo)準(zhǔn)模塊中若發(fā)生標(biāo)準(zhǔn)錯誤,會自動拋擲標(biāo)準(zhǔn)異常,無須程序員指定,throw,地點,int,*,f(),return,new int,1000000000;,i,nt,main(),int,*sp;,try,sp=f();,catch,(bad_alloc,),cout,Bad Allocation.n;,return,1;,/using sp;,10/22/2024,10,3.,捕捉異常,(Catching Exception),類型匹配,異常捕捉的類型匹配之苛刻程度可以和模板的類型匹配媲美,它不允許相容類型的隱式轉(zhuǎn)換,比如,拋擲,char,類型用,int,型就捕捉不到例如下列代碼不會輸出,“,int,exception.,”,,從而也不會輸出,“,That,s ok.,”,int,main(),try,throw,H,;,catch,(,int,),cout,int,exception.n;,cout,Thats ok.n;,10/22/2024,11,異??梢院瘮?shù)為依托,層層布網(wǎng):,下層捕捉失敗后,拋擲會繼續(xù)上傳,觸動上層捕捉直至系統(tǒng)最后一道防線,例如,下列代碼將輸出“,int,exception.”:,void,f(),try,throw,12,;,catch,(,char,),cout,“char exception.n”;,int,main(),try,f();,catch,(,int,),cout,int,exception.n;,10/22/2024,12,4.,異常申述,(Exception Description),布網(wǎng)是按類型,以便捕捉,申述也是按類型,規(guī)定拋擲的類型范圍,申述是函數(shù)對拋擲的過濾網(wǎng)格沒有函數(shù)的異常類型申述,拋擲是穿透不出函數(shù)的,10/22/2024,13,沒有申述的函數(shù),默認(rèn)為任何拋擲都可穿透該函數(shù),class A;,class B;,void f1()throw(A,B);,void f2();,void f3()throw();,對于函數(shù),g,中的調(diào)用,可能捕捉到函數(shù),f1,的和函數(shù),f2,的異常拋擲,但捕捉不到函數(shù),f3,中的任何拋擲,注:同一個函數(shù),其聲明與定義中的申述應(yīng)一致,class A;,class B;,void f1()throw(A,B),if(.)throw A;,void f2(),if(.)throw B;,void f3()throw(),if(.)throw A;,void g(),try,f1();,f2();,f3();,catch(A,),cout,“exception in An”;,catch(B,),cout,“exception in Bn”;,10/22/2024,14,捉不住處理:,拋擲而無布網(wǎng)捕捉的異常將直逼系統(tǒng)的最后一道防線,void f(),if(.),throw A,;,void g(),try,f();,catch(B,),cout,“exception Bn”;,int,main(),g();,throw A,將穿透函數(shù),f,,,g,和,main,,抵達(dá)系統(tǒng)的最后一道防線,激發(fā),terminate,函數(shù)該函數(shù)調(diào)用引起運行終止的,abort,函數(shù),最后一道防線的函數(shù)可以由程序員設(shè)置從而規(guī)定其終止前的行為,10/22/2024,15,5.,異常繼承體系,(Exception Inheritance System),異常拋擲的捕捉是類型匹配的,.,關(guān)乎類型的匹配自然納入類機制的范疇,.,因而,異常的多態(tài)是必不可少的,.,有了異常的多態(tài),就不但可以按函數(shù)調(diào)用鏈層撒網(wǎng),捕捉拋擲,還可以按類的層次進(jìn)行體系化異常捕捉,10/22/2024,16,拋擲子類可被基類捕捉,try,if(.),throw,OtherErr,;,catch,(MyException,&me),if,(string(me.what,()=,HardwareErr,)./,停機,if,(string(me.what,()=,PerformErr,)./,加工件離機,停機,if,(string(me.what,()=,OtherErr,)./,粗暴停機,catch,(exception,&e),cout,StandardExceptionn,;/,停機,10/22/2024,17,6.,異常應(yīng)用,(Exception Applications),異常特別適合于一種封閉的模塊想要設(shè)法把出乎意料的信息傳出去,作為封閉的模塊,其輸出信息的狀態(tài)模式是規(guī)定的,但當(dāng)出現(xiàn)出乎意料的情況,無法完成模塊任務(wù)的時候,就談不上輸出信息了用異常指引到另一個狀態(tài)處理器是明智的,10/22/2024,18,構(gòu)造函數(shù):,正象一個封閉的模塊,輸出狀態(tài)是一個新創(chuàng)對象任何創(chuàng)建過程中的錯誤(例如,動態(tài)內(nèi)存申請失敗等)都會導(dǎo)致模板的出乎意料這時候的狀態(tài)是不能接續(xù)后繼操作的,如:捆綁對象的操作因為沒有對象而招致失敗如果敢于正常返回,則又招致荒謬的結(jié)果,class,Date,int,year,month,day;,void,init(,int,y,int,m,int,d),if,(y,1|m12|d31),return,;/?,public,:,Date(,int,y=2000,int,m=1,int,d=1),:,year(y),month(m),day(d,),init();,void,print(),cout,year“-”month“-”,day“n”;,;,int,main(),Date ad(2000,13,1);,ad.print,();/,荒謬,:,月份為,13,10/22/2024,19,異常操作應(yīng)該恢復(fù)到對類對象進(jìn)行創(chuàng)建和使用以前的狀態(tài),void,f(),Date(2000,13,1);,ad.print,();,int,main(),try,f();,/,其他操作,catch,(out_of_range,),cout,“,對象創(chuàng)建失敗,改換門庭”,;,class,Date,int,year,month,day;,void,init(,int,y,int,m,int,d),if,(y,1|m12|d31),throw,out_of_range,;,public,:,Date(,int,y=2000,int,m=1,int,d=1),:,year(y),month(m),day(d,),init();,void,print(),cout,year“-”month“-”,day,getRadius,();,else,sp-rotate();,10/22/2024,21,動態(tài)轉(zhuǎn)型,:,對引用的動態(tài)轉(zhuǎn)型,其結(jié)果不是指針,而是一個對象,因此無法以指針值判斷也無法根據(jù)結(jié)果值,(,對象,),來得出對象的類型因而,即使轉(zhuǎn)型失敗也無法逆轉(zhuǎn)后繼執(zhí)行次序但是引用動態(tài)轉(zhuǎn)型如果失敗,將會拋擲一個標(biāo)準(zhǔn)異常,bad_cast,,這就給程序員提供了實施多態(tài)的手段,int,main(),Circle c;,Rectangle r;,h(c,);/,引用的動態(tài)轉(zhuǎn)型,h(r,);,class,Shape,public,:,virtual double,area()=0;,;,class,Circle:,public,Shape,public,:,double,area(),void,getRadius,(),;,class,Rectangle:,public,Shape,public,:,double,area(),void,rotate(),;,void,h(Shape,&,rs,),try,dynamic_cast,(,rs).getRadius,();,catch(bad_cast,),r,s.rotate,();,10/22/2024,22,7.,非錯誤處理,(Non-Error,Proccessing,),循環(huán)控制,多重循環(huán)控制中,當(dāng)某個條件滿足時,需要立刻退出所有循環(huán)體時,一般用,goto,語句反而比較現(xiàn)實否則一重一重地退,編程復(fù)雜,性能也連累