《C++程序设计语言》课件第13章_第1页
《C++程序设计语言》课件第13章_第2页
《C++程序设计语言》课件第13章_第3页
《C++程序设计语言》课件第13章_第4页
《C++程序设计语言》课件第13章_第5页
已阅读5页,还剩28页未读 继续免费阅读

下载本文档

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

文档简介

第13章异常处理

13.1概述

13.2C++异常处理结构try、throw和catch

13.3异常类层次*13.4捕获new操作所产生的异常*13.5C++标准库异常层次

小结

练习题

本章要点:

C++异常处理结构;

C++异常类的层次化组织;

捕获new产生的异常;

C++标准库异常类层次。

13.1概述

正如7.3节所述,对于一个实用的程序而言,没有错误处理是不可能的。实际的(大型)程序是由许多人在不同的时间内开发出来的,许多出错处理任务并不一定能在(或者不应当在)发现出错的地方完成。

一个欠缺良好结构的程序(有时也可能是由于没有语言支持机制造成的),对其错误通常采用判断语句(如C++中的if和switch语句)进行判断与处理。这种错误的判断与处理方式带来两个问题:

(1)大量的错误处理代码与程序的功能代码交织在一起,这不仅造成了程序结构的混乱不堪,而且往往错误处理代码远远大于程序的功能代码,这使得程序的可读性与可维护性大大下降。

(2)对于某些错误而言,程序不知如何或不能够处理,因而对此类错误只能丢弃,这又往往使程序的可靠性大大下降,甚至在某些极端的情况下,程序退化成不可用。

欲正确处理一个错误,需要明确知道如下两类信息:

(1)错误发生的地点,何种类型的错误;

(2)怎样处理错误,在何处处理错误。

因此,出错处理任务应当被分解成两部分:错误处理与错误的报告。

(1)在某处(更一般地说是在某一模块)若发现错误(该错误可能是本模块中的错误,亦可能是来自其它模块中的错误),能处理,则进行处理。

(2)不能处理则应设置出错报告的条件,当满足条件时进行报告,以提供必要的信息,供可能进行错误处理的模块进行错误处理。

C++的异常处理机制(ExceptionHandling)提供了一种结构化的、能有效地捕获和处理各种类型的错误的机制。该机制将错误的报告与错误的处理显式分离,并使得系统能从导致异常的错误中恢复,恢复的过程即执行异常处理器(ExceptionHandler)。

13.2C++异常处理结构try、throw和catch

在C++中,每一个异常(Exception)都是一个错误类的实例,C++用try-catch块进行异常的捕获与处理,用throw语句进行错误的报告。

C++的异常处理结构如下:

//…

try{

//…可能出现异常的程序代码

}

catch(Error1e1){

//…对异常类Error1对象e1的处理代码

}

catch(Error2e2){

//…对异常类Error2对象e2的处理代码

}

//…

编程时,程序员将可能产生异常的代码放入try块中,try块后面是一个或多个catch块(亦称为catch子句或异常处理器)。每个catch块捕获和处理其参数表中指定的某种类别的异常。

C++语法规定:try块允许嵌套,catch块不允许嵌套,且每个catch块是互斥的。

当try块中抛出异常时,程序控制离开try块,并依次从catch块中搜索其参数类型与异常类型相匹配的异常处理器进行异常处理,之后转入到最后一个catch块后的代码执行;如果try块没有抛出异常,则跳过所有的catch异常处理器,并转入到最后一个catch块后的代码执行。13.2.1抛出异常

在程序中,若出现某一异常,而在此时又无法进行自身处理,可利用throw子句重新抛出该异常。执行throw的点称为抛出点(ThrowPoint)。throw既可以抛出一个字符串字面值(错误消息),亦可以抛出一异常类对象。抛出对象向处理该异常的异常处理器传递错误信息。下面给出一try-catch和throw的应用实例。13.2.2重新抛出异常

捕获异常的处理器(catch块)当捕获到一异常时,可能在某些情况下又不能处理该异常或不知如何处理该异常或不能完全处理该异常,此时,可利用throw语句重新抛出该异常,此时抛出的异常由其它异常处理器或系统进行处理。

例:

voidf()

{

try{

//...

}

catch(Ee){

//...

throw;

}

}13.2.3捕获所有的异常

为了捕获所有的异常,C++提供了catch()异常处理器以供处理系统中所有的catch块没有捕获和处理的异常。

例:

voidm(){

try{

//...

}

catch(...){ //任意异常处理器

//...

}

}

13.3异 常 类 层 次

如果系统中可能有多个异常,而且这些异常是相关的,那么我们就应当将这些相关的异常类进行层次化的组织(采用继承机制,树或有向无环图)。异常类的层次化组织对于正确捕获和处理异常是至关重要的。

例如,在算术运算中可能产生下述异常:

classMatherr{//...};//通用算术异常类的父类

classOverflow:publicMatherr{//...};

//上溢异常类

classUnderflow:publicMatherr{//...};

//下溢异常类

classZerodivid:publicMatherr{//...};

//被零除异常类上述异常类可按上述形式进行组织,即Matherr为所有算术类的父类,其它的Overflow、Underflow和Zerodivid类均为Matherr类的子类。异常处理器可按如下方式进行组织:

//...

try{

//...

}

catch(Overflow){//上溢错误类的捕获与处理

//...

}

catch(Underflow){//下溢错误类的捕获与处理

//...

}

catch(Zerodivid){//被零除错误类的捕获与处理

//...

}

catch(Matherr){//其它算术类错误的捕获与处理

//...

}

//...从上述例子可看出,异常处理器的排列顺序是按照异常类层次自底向上顺序进行的,这样才能保证当一个具体的或一般的算术类错误抛出时,其异常都确保能被捕获处理。

catch异常处理器的参数类型可以是错误类层次中的父类类型,此时,若实参为子类,则参数只接受其父类成员的那一部分。当catch参数表中的参数为异常类的父类的指针或引用时,实参既可以是父类的指针或引用,亦可以是子类的指针或引用,此时即可进行多态的错误处理。*13.4捕获new操作所产生的异常

从前面的讨论我们已经知道,new操作用于动态地在堆中申请内存。当new操作失败(返回值为零)时,我们可用如下方法处理该异常:

(1)采用assert宏测试new的返回值,若返回值为零,则assert宏终止程序的运行。但这并不是new异常处理的健壮机制,因为它不允许我们用任何方法从异常中恢复。

(2) C++标准指出:当出现new故障时,系统会抛出bad_alloc异常(在头文件<new>中定义),我们可利用该异常和C++的异常处理机制来处理该异常。例如:

(3)利用函数set_new_handler(void(*fp)())(在<new>中定义)进行new故障的处理,其中fp为指向一用户编写的处理该new故障的函数指针。当new故障发生时(不管在程序中的任何地方),系统通过set_new_handler函数自动跳转到fp指针所指的new故障的异常处理函数中。例如:

#include<iostream>

#include<new>

#include<cstdlib>

usingnamespacestd;

voidcustomNewHandler()

{

cerr<<“customNewHandlerwascalled”;

abort();

(4)一般而言,我们用new操作符动态申请内存空间,用delete操作符释放其动态申请的内存空间。但当内存分配之后且在执行delete之前发生了异常,则可能发生内存泄漏问题。解决该问题的方法是采用系统头文件<memery>中的auto_ptr类模板。

一个auto_ptr对象维护动态分配的内存指针,当该auto_ptr对象超出作用域时,则auto_ptr自动进行delete操作。auto_ptr类模板过载了“*”和“->”运算符,因此对auto_ptr可像一个普通指针一样使用。auto_ptr类模板及其使用方法见下例:程序运行输出结果:

Creatinganauto_ptrobjectthatpointstoanInteger

ConstructorforInteger7

Usingtheauto_ptrtomanipulatetheInteger

IntegeraftersetInteger:99

Terminatingprogram

DestructorforInteger99*13.5C++ 标准库异常层次

C++标准库提供的异常类层次中,所有的异常类都从exception(在<exception>中定义)派生而来,该基类有一个成员函数what(),每个派生异常类可重置该方法,该方法报告异常的相应信息。

从exception类可直接派生两个异常类:

runtime_error类,所有运行时异常类的父类;

logic_error类,所有程序逻辑错误类的父类。

另外,从exception中还可以派生出一些其它的异常类(系统运行时自动抛出),如:

bad_alloc,new操作失败抛出的异常;

bad_cast,dynamic_cast操作失效抛出的异常;

bad_typeid,type_id操作失效时抛出的异常。小结

C++ 的异常处理机制使得程序可结构化地捕获和处理异常,而不是任其发生和造成恶果。

每一个异常即是一个错误类的实例。C++用try-catch结构来捕获和处理程序所发生的异常。每个catch是互斥的,catch子句的参数为一个异常类对象或异常类的指针或引用,或者为char*类型。每个catch捕获并处理与其参数表一致或相容的异常对象。一般而言,系统中有多种类别的异常,我们应将这些异常进行层次化的组织。为了捕获和处理整个异常类层次中的所有异常,catch应以其参数类别按异常类层次自底向上的顺序进行排列。我们还可用catch(…)来捕获一切未知的异常。

当程序中出现异常而又无法处理或不知如何处理时,可用throw子句重新抛出该异常;当catch处理器接到一个异常而又无法处理或不知如何处理时,可用throw重新抛出该异常。

C++标准类库中,定义了except

温馨提示

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

评论

0/150

提交评论