第15章 异常处理

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
©2007 iSoftStone Holdings Ltd. All Rights Reserved. 2008年3月6日 Author:Joly,Xiang.
15.5 多路捕获
例如,操作String类对象时,预设两个异常: class String{ void f() public: { String(char*, int); class Range{ //异常类1 public: Range(int j):index(j){} int index; }; 10); class Size{}; //异常类2 char& operator[](int k){ if(0<=k && k<len) return p[k];
cerr <<"->out of range: "
//代码区3
catch(String::Size)
{ cerr <<"size illegal!\n"; } cout <<"The program will be continued here.\n\n"; //代码区4 } void main() { //代码区5 f(); cout <<"These code is not effected by probably exception in f().\n"; } 运行结果为: abcdefghij The program will be continued here These code is not effected by probably exception in f().
©2007 iSoftStone Holdings Ltd. All Rights Reserved.
2008年3月6日 Author:Joly,Xiang.
在一般情况下,被调用函数直接检测到异 常条件的存在并使用throw引发一个异常(注意, C++语言的异常是由程序员控制引发的,而不 是由计算机硬件或程序运行环境控制的);在 上层调用函数中使用try检测函数调用是否引发 异常,检测到的各种异常由catch捕获并作相应 处理。
©2007 iSoftStone Holdings Ltd. All Rights Reserved.
2008年3月6日 Author:Joly,Xiang.
15.1 异常处理概述
程序可能按编程者的意愿终止,也可能因为 程序中发生了错误而终止。例如,程序执行时遇 到除数为0或下标越界,这时将产生系统中断, 从而导致正在执行的程序提前终止。 程序的错误有两种,一种是编译错误,即语 法错误。如果使用了错误的语法、函数、结构和 类,程序就无法被生成运行代码。另一种是在运 行时发生的错误,它分为不可预料的逻辑错误和 可以预料的运行异常。
©2007 iSoftStone Holdings Ltd. All Rights Reserved.
2008年3月6日 Author:Joly,Xiang.
15.4 标准C++库中的异常类
标准C++库中包含9个异常类,它们可以分为运行 时异常和逻辑异常: length_error //运行时长度异常 domain_error //运行时域异常 out_of_range_error //运行时越界异常 invalid_argument //运行时参数异常 range_error //逻辑异常,范围异常 overflow_error //逻辑异常,溢出(上)异常 overflow_error //逻辑异常,溢出(下)异常 标准C++库中的这些异常类并没有全部被显式使 用,因为C++标准库中很少发生异常,但是这些标准 C++库中的异常类可以为编程人员,特别式自己类库 的开发者提供一些经验。
2008年3月6日 Author:Joly,Xiang.
异常处理的执行过程如下:
(1)控制通过正常的顺序执行到达try语句,然后 执行try块内的保护段。 (2)如果在保护段执行期间没有引起异常,那么 跟在try块后的catch子句就不执行,程序从异常被抛掷 的try块后跟随的最后一个catch子句后面的语句继续执 行下去。 (3)如果在保护段执行期间或在保护段调用的任 何函数中有异常被抛掷,则从通过throw运算数创建的 对象中创建一个异常对象。编译器从能够处理抛掷类 型的异常的更高执行上下文中寻找一个catch子句(或 一个能处理任何类型异常的catch处理程序)。catch处 理程序按其在try块后出现的顺序被检查。如果没有找 到合适的处理程序,则继续检查下一个动态封闭的try 块。此处理继续下去直到最外层的封闭try块被检查完。
第15章
15.1 15.2 15.3 15.4 15.5 15.6
异常处理
异常处理概述 异常处理的基本思想 C++异常处理的实现 标准C++库中的异常类 多路捕获 含有异常的程序设计
2008年3月6日星期四1时2分44秒 Author:Joly,Xiang.
在编写程序时,应该考虑确定程序可能出现 的错误,然后加入处理错误的代码。也就是说, 在环境条件出现异常情况下,不会轻易出现死机 和灾难性的后果,而应有正确合理的表现。这就 是异常处理。C++提供了异常处理机制,它使得 程序出现错误时,力争做到允许用户排除环境错 误,继续运行程序。
©2007 iSoftStone Holdings Ltd. All Rights Reserved.
2008年3月6日 Author:Joly,Xiang.
为处理可预料的错误,常用的典型方法是让被调用 函数返回某一个特别的值(或将某个按引用调用传递的 参数设置为一个特别的值),而外层的调用程序则检查 这个错误标志,从而确定是否产生了某一类型的错误。 另一种典型方法是当错误发生时跳出当前的函数体,控 制转向某个专门的错误处理程序,从而中断正常的控制 流。这两种方法都是权宜之计,不能形成强有力的结构 化异常处理模式。 异常处理机制是用于管理程序运行期间错误的一种 结构化方法。所谓结构化是指程序的控制不会由于产生 异常而随意跳转。异常处理机制将程序中的正常处理代 码与异常处理代码显式区别开来,提高了程序的可读性。
throw <表达式>; try { //try语句块 } catch(类型1 参数1) { //针对类型1的异常处理 } catch (类型2 参数2) { //针对类型2的异常处理 } … catch (类型n 参数n) { //针对类型n的异常处理 }
©2007 iSoftStone Holdings Ltd. All Rights Reserved.
©2007 iSoftStone Holdings Ltd. All Rights Reserved. 2008年3月6日 Author:Joly,Xiang.
15.3.2 异常处理的规则
(1)try分程序必须出现在前,catch紧跟出现在后。 catch之后的圆括号中必须含有数据类型,捕获是利用数 据类型匹配实现的。 (2)如果程序内有多个异常错误处理模块,则当异 常错误发生时,系统自动查找与该异常错误类型相匹配 的catch模块.查找次序为catch出现的次序。 (3)如果异常错误类型为C++的类,并且该类有其 基类,则应该将派生类的错误处理程序放在前面,基类 的错误处理程序放在后面。 (4)如果一个异常错误发生后,系统找不到一个与 该错误类型相匹配的异常错误处理模块,则调用预定义 的运行时刻终止函数,默认情况下是abort。
{
throw Range(k);
} private: char* p; int len; static int max; }; int String::max = 20; String::String(char* str, int si){ if(si<0 || max<si) } <<r.index <<endl;
©2007 iSoftStone Holdings Ltd. All Rights Reserved.
2008年3月6日 Author:Joly,Xiang.
(4)如果匹配的处理器未找到,则运行函数 terminate将被自动调用,而函数terminate的默认功能是 调用abort终止程序。 (5)如果找到了一个匹配的catch处理程序,且它 通过值进行捕获,则其形参通过拷贝异常对象进行初 始化。如果它通过引用进行捕获,则参量初始化为指 向异常对象。在形参被初始化之后,开始“循环展开 栈”的过程,这包括对那些在与catch处理器相对应的 try块开始和异常丢弃地点之间创建的(但尚未析构的) 所有自动对象的析构。析构以与构造相反的顺序进行。 然后执行catch处理程序,接下来程序跳转到跟随在最 后处理程序之后的语句。 注意:catch处理程序的出现顺序很重要,因为在 一个try块中,异常处理程序是按照它出现的顺序被检 查的。
©2007 iSoftStone Holdings Ltd. All Rights Reserved.
2008年3月6日 Author:Joly,Xiang.
15.2 异常处理的基本思想
对于中小型程序,一旦发生异常,一般 是将程序立即中断执行,从而无条件释放 系统所有资源。而对于比较大的程序来说, 如果出现异常,应该允许恢复和继续执行。 恢复的过程就是把产生异常所造成的恶劣 影响去掉,中间一般要涉及一系列的函数 调用链的退栈,对象的析构,资源的释放 等。继续运行就是异常处理之后,在紧接 着异常处理的代码区域中继续运行。
15.3.1 异常处理的语法
在C++程序中,任何需要检测异常的语句 (包括函数调用)都必须在try语句块中执行, 异常必须由紧跟着try语句后面的catch语句来捕 获并处理。因而,try与catch总是结合使用。 throw、try和catch语句的一般语法如下:
©2007 iSoftStone Holdings Ltd. All Rights Reserved. 2008年3月6日 Author:Joly,Xiang.
throw Size();
p=new char[si]; strncpy(p, str, si); len=si;
} void g(String& str){ int num=10; for(int n=0; n<num; n++) cout <<str[n]; cout <<endl; }
如果在代码区2中,构造String对象的定义为: String s("abcdefghijklmnopqrstuvwxyz",26); 则运行结果为: size illegal! The programwill be continued here These code is not effected by probable exception in f(). 类String包含了类Range和一个空类Size的定义,它 们是嵌套类。 设置Size的唯一目的就是为了作为异常类来抛掷。如果下 标值超出范围,[]运算符重载就抛掷一个Range异常。 ->在一个类定义的内部定义一个类,称为嵌套类。 嵌套类的成员函数和静态成员可以在包含该类的外部定义,但嵌套 类的作用域在包含该类定义的内部。 如果String构造函数的参数si不在给定的数值范围内,它就抛掷一 个Size异常。当函数f()开始执行时,就首先执行标志为代码区1的代码。 如果代码区1抛掷一个异常,它只能被系统默认的异常处理程序 abort()所捕获,导致终止运行。因为它不在用户定义的异常区域。 在代码区1执行之后(没有发生异常), 在try块中代码区2就开始执 行。如果这段代码直接或间接地抛掷一个异常, 若该异常的数据类型与 catch参数的数据类型匹配,跟在try块之后的catch块就可捕获这个异常。 如果它未被捕获,该异常又只能被系统默认的异常处理程序abort()捕获。 如果其中有一个catch块实际地捕获了所抛掷的异常,那么该catch 块的代码就执行。 如果这段代码没有执行终止运行的语句,没有返回语句,也没有再 抛掷语句,那么就执行代码区4的代码。如果catch抛掷一个异常throw, 则由系统默认的异常处理程序来捕获。 异常处理完后,就执行代码区4的代码,以后,函数f()正常结束。 如果代码区4中有抛掷异常, 则只能被系统默认的异常处理程序捕获。 因为它也不在用户定义的异常区域内。 在主程序中, 如果在执行代码区5的代码时,抛掷一个异常,则由 系统默认的异常处理程序捕获。因为它不是用户定义的异常区域。 在调用f()中,可能发生抛掷异常, 被程序定义的异常处理程序所 捕获。但是,从f()返回后,其它部分的代码继续运行,不受影响。 ->catch(Size)并没有对抛掷的Size对象指派名字。因为Size对象不 含数据成员,也没有必要给捕获对象一个名字。
©2007 iSoftStone Holdings Ltd. All Rights Reserved.
2008年3月6日 Author:Joly,Xiang.
15.3 C++异常处理的实现
C++语言异常处理机制的基本思想是将异常 的检测与处理分离。当在一个函数体中检测到异 常条件存在,但无法确定相应的处理方法时,将 引发一个异常,并由函数的直接或间接调用检测 并处理这个异常。这一基本思想用3个保留字实 现:throw、try和catch。其作用是: (1)try:标识程序中异常语句侦测块的开 始。 (2)throw:用来创建用户自定义类型的异 常错误。 (3)catch:标识异常错误处理模块的开始。
ቤተ መጻሕፍቲ ባይዱ
很多程序可能有若干不同种类的运行错误,它们可 以使用异常处理机制,每种错误可与一个类,一种数据 类型或一个值相关。这样,在程序中就会出现多路捕获。 例15-5
//代码区1 try{ //代码区2 String s("abcdefghijklmnop", g(s); }
多路捕捉举例(例15-5)
catch(String::Range r)
相关文档
最新文档