您好,欢迎访问三七文档
第12章异常处理异常(exception)——程序运行期出现的问题或错误。异常处理——结构化的处理异常的方法,在有可能发生异常的地方做出预见性的安排。非结构化异常处理:用exit(n)或return(n)的运行期错误处理机制,具有“一个入口,多个出口”的特点。结构化的异常处理:积极的运行期问题处理机制。当异常出现后,可按“警告—忽略”、“对话—补救”或安全退出等模式,使程序可以在对运行条件做出适当安排或改善后继续运行下去。12.1异常处理的基本语法C++的异常处理的基本思想是将异常的检测与处理分离。在一个函数体中检测到异常条件满足,但无法确定相应的处理方法时,就引发一个异常,然后由函数的直接或间接调用者处理此异常。C++的异常处理建立在三个关键字基础之上:try、catch和throw。C++异常处理语句的一般形式如下:try{//try块内监视异常if(条件)throwexception;//由throw抛出异常…;//其它语句}catch(类型1参数1){//catch块内处理代码}catch(类型2参数2){…;}……catch(类型n参数n){…;}注意:C++通过try夺取运行期的环境控制权,即异常的引发是由程序员控制的,而不是由程序运行环境或计算机硬件控制的。任何要检测异常的语句或函数调用都必须在try语句块中执行。异常由紧跟在try块后的catch语句来捕获并处理。#includeiostream.hconstdoublePI=3.1416;voidinvoke(intx){try{if(x==0)throwx+5;//抛出int型的异常if(x==1)throw'A';//抛出cahr型的异常if(x==2)throwAnapple;//抛出字符串型的异常if(x==3)throwPI;//抛出double型的异常}catch(inti){coutcatchaintegeriendl;}catch(charc){coutcatchacharcendl;}catch(charstr[10]){coutcatchastringstrendl;}catch(doubled){coutcatchadoubledendl;}}程序运行结果:catchainteger5catchacharAcatchastringAnapplecatchadouble3.1416例12.1异常处理演示。voidmain(){invoke(0);invoke(1);invoke(2);invoke(3);}编写异常处理代码的规则:(1)可以有数量不限的catch处理程序出现在try块之后,在try块出现之前不能出现catch块。编写异常处理代码的规则:(2)在关键字catch之后的圆括号内应包括数据和类型声明。因为捕获是根据throwexception语句的异常类型与之匹配来实现的,它与一般函数的作用相似。如果在编写异常处理程序的函数带有参数,参数名仍可以传入catch处理程序中。编写异常处理代码的规则:(3)如果抛出一个异常,而在通往抛出函数的调用链中找不到与之匹配的catch处理程序,运行将以调用系统terminate()函数终止。编写异常处理代码的规则:(4)如果catch中处理程序执行完毕,而无返回或终止指令,将跳过后面的catch块继续执行程序。编写异常处理代码的规则:(5)如果throw语句没有被执行,那么catch块将被忽略。(6)在实际运用中,throw执行前一定有一个条件判断。编写异常处理代码的规则:(7)throw抛出的可以是一个常量,也可以是一个变量。关键字throw还可以灵活地放到很多地方,只要try块中的语句能直接或间接地执行到它。编写异常处理代码的规则:(8)catch在比较类型匹配时并不需要完全相同。被throw抛出的异常的数据类型与catch处理程序的参数类型进行匹配的过程,由精确匹配和自动数据类型转换的匹配组成。在下列情况视为两者类型匹配:catch的参数类型与抛出异常严格匹配、catch的参数类型是被抛出异常所在类的公有基类、catch的参数类型是指向派生类的指针。12.2异常捕获12.2.1单路捕获单路捕获就是在程序中使用一个catch处理语句来捕获错误。这种处理比较简单。当C++异常处理语句一般格式式中n=1时,就是单路捕获。#includeiostream.h#includestring.hclassCRange{intx;public:CRange(inta){x=a;}intget_x(){returnx;}};classRange:publicCRange{public:Range(intb):CRange(b){};};例12.2使用try…throw…catch编写一异常处理函数,对下列程序进行异常处理。classString{char*contents;intlength;public:String(char*str){length=strlen(str);contents=newchar[length+1];strcpy(contents,str);}char&operator[](intj){RangeR(100);if(j=0&&jlength)returncontents[j];throwR;}voidprint(String&s){intj;for(j=0;j20;j++)couts[j];coutendl;}};intfunction(String&ss){try{ss.print(ss);}catch(CRangecr){coutendlOutofrangle!endl;returncr.get_x();}return0;}voidmain(){Stringx(abc);intj=function(x);coutfunction()returns:jend;;}程序输出:abcOutofrangle!function()returns:100(1)由于在String类中重载了运算符[],重载函数又调用throw语句,故在函数print()中运行for循环的s[j]时将会遇到异常抛出,根据条件在循环3次后将抛出异常。(2)Range类的异常被function()函数中的catch捕获,是由于catch的参数类型CRange为Range的公有基类。12.2.2多路捕获当C++异常处理语句格式中n大于1时,就构成多路捕获结构。多路捕获使得程序在出现一个异常时,可以由相应的处理程序进行有针对性的处理。多路捕获的异常处理比单路捕获更灵活,适用面更广.多路捕获的一般规则:(1)如果try块中的一个语句或者在try块的一个被调函数中的一个语句抛出一个异常,在沿着调用返回时该异常到达第一个catch语句,逐个查看每个catch语句处理程序,根据被抛对象,找出匹配。注意,处理程序有一定的先后顺序。多路捕获的一般规则:(2)如果找到一个匹配,就执行匹配的处理程序代码。如果没有找到匹配,则检查下一个catch语句,若所有的catch语句都找完了,还没有找到匹配的catch语句,就由调用系统函数terminate()终止调用,后者按常规再调用abort0。#includeiostream.h#includestring.hclassString{intlength;char*contents;public:String(){contents=NULL;}String(char*str){length=strlen(str);contents=newchar[length+1];strcpy(contents,str);}char*get_str(String&s){returns.contents;}};例12.3使用try…throw…catch…catch编写一异常处理函数,对下列程序进行异常处理。voidf(String&s){try{char*ss;ss=s.get_str(s);if(ss)throws;elsethrowcontentisNULL;}catch(String&s){couts.get_str(s)endl;}catch(charinfo[]){coutinfoendl;coutCaughtaknownexception.endl;;}}执行结果如下:Hello!Hi!contentisNULLCaughtaknownexception.voidmain(){Strings1(Hello!);Strings2(Hi!);Strings3;f(s1);f(s2);f(s3);}12.3异常处理的其它用法讨论其它三种常见异常处理用法:异常的限制异常重抛异常成组1.异常的重抛同一异常可以多次抛出,在第一次抛出写上异常名,而后只需调用“throw”即可完成重抛。限制:一个异常只能在一个catch块(或在该块调用的函数中重抛;再次抛出异常时,不能由同一个catch块捕获,它将传给外面的try-catch块处理。#includeiostream.hvoidf(){try{throwHello;}catch(char*str){coutCaughtstrinsidef()endl;throw;//重抛}}voidmain(){try{f();}catch(char*str){coutCaughtstrinsidemain()endl;}}程序执行结果如下:CaughtHelloinsidef()CaughtHelloinsidemain()例12.4异常的重抛2.异常的限制在异常处理中,由于捕获和抛出一个异常会影响到一个函数与其它函数的相互关系。因此,C++异常机制允许在函数定义后面增加一个抛出类型说明,以限制该函数可以抛出的异常类型。异常限制的一般格式如下:返回值类型函数名(参数表)throw(异常类型列表){….}使用时应特别注意,经这样定义的函数,抛出的异常数据只能是异常类型列表中的一种。如果一个函数抛出的异常没有在抛出类型列表中说明或者从所列数据类型之一派生,默认的异常处理过程就是调用名为unexpected()的函数,该函数又调用terminate()函数,后者依次再调用abort()函数终止程序运行。其中,对unexpected()和terminate()用户可以提供自己的函数定义。例12.3异常限制演示#includeiostream.hvoidinvoke(inttest)throw(int,char){if(test==0)throwtest;(test==1)throw'a';if(test==2)throw123.23;}voidf(intt){try{invoke(t);}catch(intj){coutCaughtanintegerjendl;}catch(charc){coutCaughtachar:cendl;}catch(doubled){coutCaughtadoubledendl;}}执行结果如下:Caughtaninteger0Caughtachar:aAbnormalprogramterminatevoidmain(){f(0);f(1);f(2);coutEndendl;}3.异常成组成组——将多个有某种关联的异常放在一组。这些异常通常属于某一个方面的异常。比如文件异常组。在C++异常处理中,有两种方式把多个异常成组。它们是:异常枚举成组和异常派生成组。#includeiostream.henumerrs{err0,err1,err2};voidf(inttest){try{if(test==0)throwerr0;if(test==1)throwerr1;if(test==2)throwerr2;}
本文标题:13异常处理
链接地址:https://www.777doc.com/doc-3369358 .html