第7章 异常处理_第1页
第7章 异常处理_第2页
第7章 异常处理_第3页
第7章 异常处理_第4页
第7章 异常处理_第5页
已阅读5页,还剩33页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、第7章 异常处理 写函数库的程序员可以检测到库函数运行时的错误(如数写函数库的程序员可以检测到库函数运行时的错误(如数组访问越界),但通常却不知道应该如何处理这些错误组访问越界),但通常却不知道应该如何处理这些错误 异常处理的基本想法是,让一个函数在发现了自己无法处异常处理的基本想法是,让一个函数在发现了自己无法处理的错误时抛出一个异常,希望它的(直接或间接)调用理的错误时抛出一个异常,希望它的(直接或间接)调用者能够处理这个问题。者能够处理这个问题。异常处理 传统错误处理方法 异常处理机制 抛出异常 捕获异常 处理异常 异常规格说明程序逻辑经常对决定程序下一步怎样执行的条件进行测试程序逻辑经

2、常对决定程序下一步怎样执行的条件进行测试执行一个任务如果这个任务没有正确执行 则执行错误处理执行下一个任务如果该任务没有正确执行 则执行错误处理传统错误处理方法 可以处理的错误在发生错误的地方就地处理可以处理的错误在发生错误的地方就地处理 在检查到一个在局部无法处理的问题时,一个函数可以:在检查到一个在局部无法处理的问题时,一个函数可以: 终止程序终止程序 abort() /exit() 返回一个表示返回一个表示“错误错误”的值。的值。int 返回一个合法值,让程序处于某种非法的状态返回一个合法值,让程序处于某种非法的状态。errno 调用一个预先准备好在出现调用一个预先准备好在出现“错误错误

3、”的情况下用的函数。的情况下用的函数。处理错误的传统方法 处理错误的传统方法:错误处理代码是在整个系统代码中分处理错误的传统方法:错误处理代码是在整个系统代码中分布的。代码中可能出错的地方都要布的。代码中可能出错的地方都要当场进行当场进行错误处理。在写错误处理。在写程序时,必须知道所有的错误该如何处理程序时,必须知道所有的错误该如何处理 好处好处: 程序员阅读代码时能够程序员阅读代码时能够直接直接看到错误处理情况,确看到错误处理情况,确定是否实现了正确的错误检查。定是否实现了正确的错误检查。 问题问题: 代码中受到错误处理的代码中受到错误处理的“污染污染”,使应用程序本身使应用程序本身的代码更

4、加晦涩难懂,难以看出代码功能是否正确实现。的代码更加晦涩难懂,难以看出代码功能是否正确实现。这样就使代码的这样就使代码的理解和维护更加困难理解和维护更加困难。面向对象中的异常处理 面向对象中,程序员经常做的是一些工具(类的设计面向对象中,程序员经常做的是一些工具(类的设计与实现)与实现) 这些工具能够检测出错误,但往往不知道该如何处理这些工具能够检测出错误,但往往不知道该如何处理错误。错误的处理是由工具的使用者决定错误。错误的处理是由工具的使用者决定 需要一种机制能将检测到的错误告诉使用者需要一种机制能将检测到的错误告诉使用者异常处理 传统错误处理方法 异常处理机制 抛出异常 捕获异常 处理异

5、常 异常规格说明8异常处理的基本思想函数f()捕获并处理异常函数h() 引发异常函数g()调用者异常传播方向调用关系异常处理 C+的新异常处理特性:的新异常处理特性: 异常处理将异常处理将检测发现检测发现错误的代码与错误的代码与处理处理错误的代码分错误的代码分开来。程序员的工作也可做相应分工(例如,库函数开来。程序员的工作也可做相应分工(例如,库函数程序员负责检测异常,而调用库函数的另一程序员则程序员负责检测异常,而调用库函数的另一程序员则负责捕获与处理异常)。负责捕获与处理异常)。 使程序员可以删除程序执行使程序员可以删除程序执行“主线条主线条”中的错误处理中的错误处理代码,从而提高程序的可

6、读性和可维护性。代码,从而提高程序的可读性和可维护性。异常处理基础简介 如果某段程序可能会抛出异常,则必须通知系统启动如果某段程序可能会抛出异常,则必须通知系统启动异常处理机制。即通过异常处理机制。即通过try语句块实现。语句块实现。 异常处理代码的一般形式:异常处理代码的一般形式:try可能抛出异常的代码 catch(类型1 参数1) 处理该异常的代码 catch(类型2 参数2) 处理该异常的代码 Try语句块中包含了可能抛出异常的代码,一旦抛出了异常,则退出try语句块,进入try后面的异常捕获和处理异常处理 传统错误处理方法 异常处理机制 抛出异常 捕获异常 处理异常 异常规格说明抛出

7、异常 如果程序发生异常情况,而在当前的环境中获取不到异常处理如果程序发生异常情况,而在当前的环境中获取不到异常处理的足够信息,我们可以的足够信息,我们可以创建一包含出错信息的对象并将该对象并将该对象抛出当前环境,发送给更大的环境中。这称为异常抛出。抛出当前环境,发送给更大的环境中。这称为异常抛出。 例1 throw myerror(“something bad happened”); myerror是一个类,它以字符串变量为参数 例2 throw int (5) int是一个内部类型,5是一个int类型的常数 throw与其操作数 抛出异常的语句形式:抛出异常的语句形式: throw ; th

8、row通常指定一个操作数(或不指定操作数的特殊情况)通常指定一个操作数(或不指定操作数的特殊情况)。throw的操作数可以是任何类型,如果操作数是个对象,的操作数可以是任何类型,如果操作数是个对象,则称为异常对象。也可以抛出条件表达式而不是抛出对象,则称为异常对象。也可以抛出条件表达式而不是抛出对象,可以抛出不用于错误处理的对象。可以抛出不用于错误处理的对象。 抛出异常时,生成和初始化抛出异常时,生成和初始化throw操作数的一个临时副本,操作数的一个临时副本,然后这个临时对象初始化异常处理器中的参数。异常处理器然后这个临时对象初始化异常处理器中的参数。异常处理器执行完毕和退出时,删除临时对象

9、执行完毕和退出时,删除临时对象。 异常抛出实例:异常抛出实例:定义一个除法函数,当除数为定义一个除法函数,当除数为0时,抛出一个用户时,抛出一个用户定义的定义的异常类对象异常类对象,该对象能告诉用户发生了除零该对象能告诉用户发生了除零错误。错误。异常抛出实例 异常类定义 / Class DivideByZeroException to be used in exception / handling for throwing an exception on a division by zero.class DivideByZeroException private: const char *me

10、ssage; public: DivideByZeroException() : message( attempted to divide by zero ) const char *what() const return message; ;记录出现的异常情况Message的默认值告诉用户出现了什么异常异常抛出实例 异常抛出double Div(int x, int y ) if ( y = 0 ) throw DivideByZeroException(); return static_cast ( x ) / y; 这条语句用默认构造函数生成了一个DivedeByZeroExceptio

11、n类的对象,并把这个对象返回给调用它的函数,div函数执行结束异常处理 传统错误处理方法 异常处理机制 抛出异常 捕获异常 处理异常 异常规格说明异常捕获 一个函数抛出异常,它必须假定该异常能被捕获和处理。异常捕获机制使得C+可以把问题集中在一处解决。catch捕获异常 异常处理器放在catch块中, 形式如下:catch ( ) catch处理器定义自己的范围。catch在括号中指定要捕获的对象类型。catch处理器中的参数可以命名也可以无名。如果是命名参数,则可以在处理器中引用这个参数。 如果是无名参数(只指定匹配抛出对象类型的类型),则信息不从抛出点传递到处理器中,只是控制从抛出点转到处

12、理器中许多异常都可以这样。 catch () 捕获任意类型的异常。异常捕获原理 如果一个异常信号被抛出,异常处理器中第一个参数与异常抛出对象相匹配的函数将捕获该异常信号,然后进入相应的catch语句,执行异常处理程序。捕获异常的匹配规则 匹配条件:下列情况下,catch处理器参数匹配所抛出对象的类型: 1、 实际是同一类型。 2、catch处理器参数类型是所抛出对象类型的public基类。 3、 处理器参数为基类指针或引用类型,而抛出对象为派生类指针或引用类型。 4、catch处理器为catch(.),捕获任意类型的异常。 捕获异常的匹配规则(续) 匹配结果:抛出异常对象类型与catch处理器

13、参数类型相符时,则两者相匹配, 程序将执行该类型的catch块(即该类型的异常处理器)。 匹配顺序:catch中在当前活动try块后面第一个匹配所抛出异常对象的异常处理器将捕获该异常。按顺序搜索异常处理器,寻找匹配项,并执行第一个匹配的处理器。处理器执行完毕时,控制恢复到最后一个catch块后面的第一条语句。捕获异常的匹配规则(续) 无匹配情况:若某个抛出对象没有任何匹配的异常处理器,这时匹配搜索会继续到外面一层try块。这个过程一直继续,若最终还是没有任何匹配的异常处理器。这时调用terminate(默认调用abort)终止程序。 多匹配情况:若几个异常处理器都匹配所抛出的对象,这可能有几个

14、原因: 第一,有一个捕获任何异常的catch()处理器。 第二,由于继承层次,派生类对象可以由派生类类型的异常处理器和基类类型的异常处理器捕获。这时执行第一个匹配的异常处理器。捕获异常的匹配规则(续) catch(.)总是作为try块后面的处理器列表中最后一个处理器。 捕获基类类型的异常处理器放在捕获派生类类型的异常处理器之后。 将带void *参数类型的异常处理器放在具有其他指针类型的异常处理器后面。除零异常的捕获int main() int number1, number2; double result; cout number1 number2 ) try result = Div( n

15、umber1, number2 ); cout The quotient is: result endl; catch ( DivideByZeroException ex ) cout Exception occurred: ex.what() n; cout nEnter two integers (end-of-file to end): “; cout endl; return 0;Try语句块中包含了可能抛出异常的代码Div,一旦抛出了异常,则退出try语句块,进入try后面的异常捕获和处理double Div(int x, int y ) if ( y = 0 ) throw Di

16、videByZeroException(); return static_cast ( x ) / y; int main() int number1, number2; double result; cout number1 number2 ) try if (number2=0) throw DivideByZeroException(); result = static_cast( number1)/number2; cout The quotient is: result endl; catch ( DivideByZeroException ex ) cout Exception o

17、ccurred: ex.what() n; cout nEnter two integers (end-of-file to end): ; cout endl; return 0;该程序实行了什么功能?26输出结果Enter tow integers (end-of-file to end); l00 7The quotient is: 14.2857Enter tow integers (end-of-file to end); 100 0Exception occurred: attempted to divide by zeroEnter tow integers (end-of-fi

18、le to end); 33 9The quotient is: 3.66667Enter tow integers end-of-file to end): 异常抛出与检测实例二int Div(int x, int y) if (y=0) throw y; return x/y;抛出的异常不一定是对象,可以是一个结果为内置类型的表达式int main() try cout Div(6,3) endl; cout Div(10,0) endl; cout Div(5,2) endl; catch (int) cout divide by zero endl; cout Its Over end

19、l; return 0;2divide by zeroIts Over调用一个函数时可能会收到一个异常。调用一个函数时可能会收到一个异常。如何知道是否会收到异常呢?如何知道是否会收到异常呢?收到的是什么异常?收到的是什么异常?异常规格声明异常处理 传统错误处理方法 异常处理机制 抛出异常 捕获异常 处理异常 异常规格说明异常规格说明传统函数声明:返回类型 函数名(形式参数表);函数可以抛出任何异常。通常我们希望在调用函数时,知道该函数会抛出什么样的异常。所以允许在函数原型声明中指出void f() throw(toobig, toosmall, divzero);函数会抛出toobig, to

20、osmall, divzero三种异常void f() throw();函数不会有异常抛出。#include class up; class down;void f(int i) throw(up, down);int main() for (int i=1;i=3;+i) try f(i); catch (up) cout up catched endl; catch (down) cout down catched endl; return 0;void f(int i) throw(up,down) switch(i) case 1: throw up(); case 2: throw

21、down(); up catcheddown catched示例#include char *ptr; try /异常模块 if(ptr=new char64*1024=NULL) throw”Not Enough Memory!”; Catch(char *str) /异常错误处理模块/ 错误处理代码Cout“Exception:”strendl; 控制通过正常的顺序执行到try语句,执行try块内的保护段; 如果保护段内没有异常,则后面的catch子句不被执行,程序从异常被抛掷的try块后的最后一个catch子句后面的语句继续执行 如果在保护段执行期间或者在保护段调用的任何函数(直接或者间

22、接的调用)中有异常被抛掷,则从通过throw运算数创建的对象中创建一个异常对象(可能包含一个拷贝构造函数) 如果匹配的处理器没有找到,则函数terminate将被自动调用(调用abort终止程序) 如果找到了一个匹配的catch程序,且它通过值进行捕获,则其形参通过拷贝异常对象进行初始化。#includevoid Excp();Ccass EXpublic EX();EX(); ;Class Demopublic: Demo()cout“creating a Demo object.”endl;Demo()cout“Deleting Demo Object.”endl; ;void Excp()Demo A;coutExcp functi

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论