您好,欢迎访问三七文档
当前位置:首页 > 行业资料 > 其它行业文档 > 第12章 异常处理(2011)
20009-3-241面向对象程序设计(下)课程讲义——C++任课教师:叶亚琴所在院系:信息工程学院软件工程系20009-3-242第12章异常处理什么是异常处理对运行时出现的差错以及其他例外情况的处理。异常处理的基本思想错误对于编程人员可以预料到但却无法避免发现错误的函数又并不具备处理错误的能力C++异常处理机制:异常引发与处理可不在同一位置和层次。好处:底层函数专注解决算法;上层负责后勤、善后工作20009-3-243第12章异常处理有哪些异常需要处理系统异常(内存问题、指针问题等)自定义异常:如分母为0时、指针为空时、…异常处理的实质:(举一个例子说明)在合适的地方处理if(){…}20009-3-244第12章异常处理——异常处理方法方法一:在函数中设置处理异常的程序段。缺点:会使程序过于复杂和庞大。方法二:发出一个异常信息传给它的上一级。上级捕捉到这个信息后进行处理。特点:效率高,程序代码简洁。20009-3-245第12章异常处理——C++异常处理机制由检查(try)、抛出(throw)和捕捉(catch)三部分构成。注意:把需要检查的语句放在try块中;throw用来当出现异常时发出一个异常信息;而catch则用来捕捉异常信息,如果捕捉到了异常信息,就处理它。20009-3-246throw语句一般是由throw运算符和一个数据组成的,其形式为:throw表达式;try-catch的结构为:try{被检查的语句}catch(异常信息类型[变量名]){进行异常处理的语句}第12章异常处理——C++异常处理机制20009-3-247第12章异常处理——C++异常处理流程(1)首先把可能出现异常的、需要检查的语句或程序段放在try后面的花括号中。(2)程序开始运行后,按正常的顺序执行到try块,开始执行try块中花括号内的语句。如果在执行try块内的语句过程中没有发生异常,则catch子句不起作用,流程转到catch子句后面的语句继续执行。(3)如果在执行try块内的语句(包括其所调用的函数)过程中发生异常,则throw运算符抛出一个异常信息。throw抛出异常信息后,流程立即离开本函数,转到其上一级的函数(main函数)。20009-3-248在VC++6.0环境中,为了使用异常处理机制,需要进行以下设置:打开ProjectSettings对话框。选择C/C++选项卡。在Category栏中选择C++language。选择EnableExceptionHandling。第12章异常处理——VC++设置20009-3-249例处理分母为零的异常#includeiostream.hintDiv(intx,inty);intmain(){try{cout5/2=Div(5,2)endl;cout8/0=Div(8,0)endl;cout7/1=Div(7,1)endl;}catch(int){coutexceptofdevidingzero.\n;}coutthatisok.\n;return0;}intDiv(intx,inty){if(y==0)throwy;returnx/y;}程序运行结果如下:5/2=2exceptofdevidingzero.thatisok.10#includeiostreamusingnamespacestd;voidmain(){char*ptr;try//异常模块{if((ptr=newchar[64*1024])==NULL)throwNotEnoughMemory!;}catch(char*str)//异常错误处理模块{//……错误处理代码coutException:strendl;}}例处理内存分配的异常20009-3-2411例14.1给出三角形的三边a,b,c,求三角形的面积。只有a+bc,b+ca,c+ab时才能构成三角形。设置异常处理,对不符合三角形条件的输出警告信息,不予计算。先写出没有异常处理时的程序:#includeiostream#includecmathusingnamespacestd;intmain(){doubletriangle(double,double,double);doublea,b,c;cinabc;while(a0&&b0&&c0){couttriangle(a,b,c)endl;cinabc;}return0;}20009-3-2412doubletriangle(doublea,doubleb,doublec){doublearea;doubles=(a+b+c)/2;area=sqrt(s*(s-a)*(s-b)*(s-c));returnarea;}运行情况如下:654↙(输入a,b,c的值)9.92157(输出三角形的面积)11.52↙(输入a,b,c的值)0.726184(输出三角形的面积)121↙(输入a,b,c的值)0(输出三角形的面积,此结果不对,不是三角形)106↙(输入a,b,c的值)(结束)20009-3-2413修改程序,在函数traingle中对三角形条件进行检查,如果不符合三角形条件,就抛出一个异常信息,在主函数中的try-catch块中调用traingle函数,检测有无异常信息,并作相应处理。修改后的程序如下:#includeiostream#includecmathusingnamespacestd;voidmain(){doubletriangle(double,double,double);doublea,b,c;cinabc;try//在try块中包含要检查的函数{while(a0&&b0&&c0){couttriangle(a,b,c)endl;cinabc;}}catch(double)//用catch捕捉异常信息并作相应处理{couta=a,b=b,c=c,thatisnotatriangle!endl;}coutendendl;}doubletriangle(doublea,doubleb,doublec)//三角形面积{doubles=(a+b+c)/2;if(a+b=c||b+c=a||c+a=b)throwa;//抛出异常信息returnsqrt(s*(s-a)*(s-b)*(s-c));}程序运行结果如下:654↙(输入a,b,c的值)9.92157(计算出三角形的面积)11.52↙(输入a,b,c的值)0.726184(计算出三角形的面积)121↙(输入a,b,c的值)a=1,b=2,c=1,thatisnotatriangle!(异常处理)end20009-3-2415第12章异常处理——C++异常处理机制(1)被检测的函数必须放在try块中,否则不起作用。(2)try块和catch块作为一个整体出现。(3)try和catch块中必须用花括号括起来。(4)try-catch结构中只能有一个try块,却可以有多个catch块,以便与不同的异常信息匹配。(5)catch后一般只写异常的类型,如:catch(double)(6)catch(…)可以捕捉任何类型的异常信息,如catch(…){;}(7)trycatch结构可以与throw出现在同一个函数中,也可以不在同一函数中。找:本函数→最近的(8)throw将当前处理的异常信息再次抛出→上一层(9)如throw抛出的异常找不到与之匹配的catch块,系统就会调用系统函数terminate,程序终止。20009-3-2416例14.2在函数嵌套的情况下检测异常处理。这是一个简单的例子,用来说明在try块中有函数嵌套调用的情况下抛出异常和捕捉异常的情况。请自己先分析以下程序。#includeiostreamusingnamespacestd;intmain(){voidf1();try{f1();}//调用f1()catch(double){coutOK0!endl;}coutend0endl;return0;}voidf1(){voidf2();try{f2();}//调用f2()catch(char){coutOK1!;}coutend1endl;}voidf2(){voidf3();try{f3();}//调用f3()catch(int){coutOk2!endl;}coutend2endl;}voidf3(){doublea=0;try{throwa;}//抛出异常catch(float){coutOK3!endl;}coutend3endl;}运行结果:OK0!end02011-4-2617catch(double)catch(char)catch(int)catch(float)doublea;(1)函数嵌套时异常处理示意图20009-3-2418(2)如果将f3函数中的catch子句改为catch(double),而程序中其他部分不变,则程序运行结果如下:OK3!(在f3函数中捕获异常)end3(执行f3函数中最后一个语句时的输出)end2(执行f2函数中最后一个语句时的输出)end1(执行f1函数中最后一个语句时的输出)end0(执行主函数中最后一个语句时的输出)(3)如果在此基础上再将f3函数中的catch块改为catch(double){coutOK3!endl;throw;}程序运行结果如下:OK3!(在f3函数中捕获异常)OK0!(在主函数中捕获异常)end0(执行主函数中最后一个语句时的输出)2011-4-2622#includeiostreamusingnamespacestd;voidMyFunc(void);classExpt{public:Expt(){};~Expt(){};constchar*ShowReason()const{returnExpt类异常。;}};例:使用带析构语义的类的C++异常处理20009-3-24232011-4-2624classDemo{public:Demo();~Demo();};Demo::Demo(){cout构造Demo.endl;}Demo::~Demo(){cout析构Demo.endl;}例:使用带析构语义的类的C++异常处理2011-4-2625voidMyFunc(){DemoD;cout在MyFunc()中抛掷Expt类异常。endl;throwExpt();}intmain(){cout在main函数中。endl;try{cout在try块中,调用MyFunc()。endl;MyFunc();}例:使用带析构语义的类的C++异常处理2011-4-2626catch(ExptE){cout在catch异常处理程序中。endl;cout捕获到Expt类型异常:;coutE.ShowReason()endl;}catch(char*str){cout捕获到其它的异常:strendl;}cout回到main函数。从这里恢复执行。endl;return0;}例:使用带析构语义的类的C++异常处理2011-4-2627程序运行结果为:在main函数中。在try块中调用MyFunc()。构造Demo。在MyFunc()中抛掷Expt类异常。析构Demo。在catch异常处理程序中。捕获到Expt类型异常:Expt类异常。程序运行回到main函数。从这里恢复执行。例:使用带析构语义的类的C++异常处理
本文标题:第12章 异常处理(2011)
链接地址:https://www.777doc.com/doc-3178380 .html