2012异常处理.doc

上传人:新** 文档编号:562044170 上传时间:2024-03-31 格式:DOC 页数:24 大小:121KB
返回 下载 相关 举报
2012异常处理.doc_第1页
第1页 / 共24页
2012异常处理.doc_第2页
第2页 / 共24页
2012异常处理.doc_第3页
第3页 / 共24页
2012异常处理.doc_第4页
第4页 / 共24页
2012异常处理.doc_第5页
第5页 / 共24页
点击查看更多>>
资源描述

《2012异常处理.doc》由会员分享,可在线阅读,更多相关《2012异常处理.doc(24页珍藏版)》请在金锄头文库上搜索。

1、C+之异常处理一个好的程序应该能对多种不同的特殊情况,做出不同的反应,对于突发情况也应有对应的处理方法。我们在编程时应考虑到各种突发情况,并在程序中给出解决方案,使程序的健壮性增强。假设有一个司机从A地开车前往B地。若在某处有一岔路口,一般选择左边,路程会近一些。但当司机选择左边,将车开到途中时发现正在修路(突发情况),无法通过。这时,司机就会掉头回到刚才的岔路口处,重新选择右边的路,继续前进。 我们所编的程序也应该像这样,有一定的智能化的设计。这就要求在编写程序时,应该试着确定程序可能出现的错运,然后加入处理错误的代码。例如:当程序执行文件I0操作时,应测试文件打开以及读写操作是否成功,并且

2、在出现错误时做出正确的反应。随着程序复杂性的增加,为处理错误而必须包括在程序中代码的复杂性也相应地增加了。为使程序更易于测试和处理错误,C+实现了异常处理机制。一、异常概念 1异常的概念程序的错误,一种是编译错误,即语法错误。如果使用了错误的语法、函数、结构和类,程序就无法被生成运行代码。另一种是在运行时发生的错误,它分为不可预料的逻辑错误和可以预料的运行异常。运行异常,可以预料,但不能避免,它是由系统运行环境造成的。如,内存空间不足,而程序运行中提出内存分配申请时,得不到满足,就会发生异常:#include/void f(char *str)ifstream source(str); 打开s

3、tr串中的文件if(sourcefail()打不开cerr Error opening the file:str endl; exit(1); 退出程序 /当程序对文件打不开时,程序会打印提示信息,并由exit(1)函数退出。这样就不至于会因为文件打不开而导致整个程序在运行过程中停滞或错乱.2异常的基本思想 在小型程序中,一旦发生异常,一般是将程序立即中断运行,从而无条件释放所有资源。对于大型程序来说,运行中一旦发生异常,应该允许恢复和继续运行。恢复的过程就是把产生异常所造成的恶劣影响去掉,中间可能要涉及一系列的函数调用链的退栈,对象的析构,资源的释放等。继续运行就是异常处理之后,在紧接着异常

4、处理的代码区域中继续运行。在C+中,异常是指从发生问题的代码区域传递到处理问题的代码区域的一个对象。见图 :发生异常的地方在函数k()中,处理异常的地方在其上层函数f()中,处理异常后,函数k()和g()都退栈,然后程序在函数f()中继续运行。如果不用异常处理机制,在程序中单纯地嵌入错误处理语句,要实现这一目的是艰难的。 异常的基本思想是:(1)实际的资源分配(如内存申请或文件打开)通常在程序的低层进行,如图中的k()。(2)当操作失败、无法分配内存或无法打开一个文件时在逻辑上如何进行处理通常是在程序的高层,如图中的f(),中间还可能有与用户的对话。 (3)异常为从分配资源的代码转向处理错误状

5、态的代码提供了一种表达方式。如果还存在中间层次的函数,如图中的g(),则为它们释放所分配的内存提供了机会,但这并不包括用于传递错误状态信息的代码。 从中可以看出,C什异常处理的目的,是在异常发生时,尽可能地减小破坏,周密地善后,而不去影响其它部分程序的运行。-这在大型程序中是非常必要的。例如对于以前所讲的程序调用关系,如处理文件打开失败异常的方法,那么,异常只能在发生的函数k()中进行处理,无法直接传递到函数f()中,而且调用链中的函数g()的善后处理也十分困难。二、异常的实现使用异常的步骤是:(1)定义异常(try语句块) 将那些可能产生错误的语句框定在try语句中;(2)定义异常处理(ca

6、tch语句块)将异常处理的语句放在catch块中,以便异常被传递过来时就处理它;(3)抛掷异常(throw语句)检测是否产生异常,若产生异常,则抛掷异常。例如,下面的程序,设置了防备文件打不开的异常:例题1#include #include #include void main(int argc,char *argv) ifstream source(argv1); /打开文件 char line128;try if(source.fail() /如果打开失败throw argv1;catch (char *s) couterror opening the filesendl; exit(1)

7、; while(!source.eof() source.getline(line,sizeof(line);coutline提示符后输入命令 ch10_1 abc.txt屏幕显示结果为: error opening the file abc.txt若输入命令 ch10_1 xyz.txt则屏幕显示结果为: How are you? Fine!例题2:一个除零异常:#includedouble Div(double,double);void main()try cout7.3/2.0=Div(7.3,2.0)endl; cout7.3/0.0=Div(7.3,0.0)endl; cout7.3

8、/1.0=Div(7.3,1.0)endl;catch(double)coutexcept of deviding zero!n; coutThat is ok.n;double Div(double a,double b) if(b=0.0) throw b; return a/b; 运行结果为:7.3/2.0=3.65except of deviding zero!That is ok.三、 异常处理机制在处理程序和语句之间的相互作用使异常在大型应用程序中变得复杂。通常人们希望抛掷被及时捕获,以避免程序突然终止。此外,跟踪抛掷很重要,因为捕获确定该程序的后继进展。例如,抛掷和捕获可以用来重

9、新开始程序内的一个过程,或者从应用程序的一部分跳到另一部分,或者回到菜单。例如,项目的代码说明了异常处理机制。void f() try g(); catch(Range) / catch (Size) / catch ()void g()h();void h()try h1();catch(Size)/.throw 10;catch(Matherr)/.void h1()/.throw(Size);try/.throw Range;h2();h3();catch(Size)/.throw; void h2()/.throw Matherr;void h3()/.throw Size;函数f()

10、中的catch(.)块,参数为省略号,定义一个默认的异常处理程序。通常这个处理程序应在所有异常处理块的最后,因为它与任何throw都匹配,目的是为避免定义的异常处理程序没能捕获抛掷的异常而使程序运行终止。函数h()中的catch(Size)块,包含有一个抛掷异常语句throw 10,当实际执行这条语句时,将沿着调用链向上传递被函数f()中的catch(.)所捕获。如果没有f()中的catch(.),那么,异常将被系统的terminate()函数调用,后者按常规再调用abort()。函数h1()中的抛掷throw Size,由于不在本函数的try块中,所以只能沿函数调用链向上传递,结果被h()中

11、的catch(Size)捕获。函数h1()中的抛掷throw Range,在try块中,所以首先匹配try块后的异常处理程序,可是没有被捕获,因而它又沿函数调用链向上,在函数f()中,catch(Range)块终于捕获了该抛掷。函数h1()中的catch(Size)块,包含一个抛掷throw,没有带参数类型,它表示将捕获到的异常对象重新抛掷出去,于是,它将沿函数调用链向上传递,在h()中的catch(Size)块,捕获了该抛掷。函数h2()中的抛掷throw Matherr,首先传递给h1()中的catch块组,但未能被捕获,然后继续沿调用链向上,在h()中的catch(Matherr)块,捕

12、获了该抛掷。函数h3()中的抛掷throw Size,向上传递给h1()中的catch块组,被catch(Size)块捕获。四、 使用异常的方法可以把多个异常组成族系。构成异常族系的一些实力又数学错误异常族系和文件处理错误异常族系。在C+代码中把异常组在一起有两种方式:异常枚举族系和异常派生层次结构。例如,下面的代码是一个异常枚举族系的例子:enmu FileErrorsnonExist,wrongformat,diakSeekError,.;int f() try /. throw wrongFormat;catch(FileErrors fe) switch(fe) case nonExi

13、st: /.case wrongFormat: /. case diskSeekError: /./.在try块中有一个throw,它抛掷一个FileError枚举中的常量。这个抛掷可被catch(FileErrors)块捕获到,接着后者执行一个switch,对照情况列表,匹配捕获到的枚举常量值。上面的异常族系也可按异常派生层次结构来实现,如下例所示:class FileErrors;class NonExist:public FileErrors;class WrongFormat:public FileErrors;class DiskSeekError:public FileErrors;int f() try /. throw WrongFormat;catch(NonExist) /.catch(DiskSeekError) /.catch(FileErrors) /./.上面的各异常处理程序块定义了针对类NonExist和DiskSeekError的派生异常类对象,针对FileErrors的异常处理,既捕获FileErrors类对象,也捕获WrongFormat对象。异常捕获的规则除了前面所说的,必须严格匹配数据类型外,对于类的派生,下列情况可以捕获异常:(1) 异常处理的数据类型是公有基类,抛掷异常的数据类型是

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 生活休闲 > 社会民生

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号