异常处理PPT课件
异常处理在C++编程中已经普遍采用,成为提高程序健壮性 的重要手段之一。
第十章 异常处理
10.1 异常的概念
10.2 异常处理的机制
10.3 捕获异常
10.4 异常的重新抛出 和catch_all子句
10.5 异常规范
10.6 异常和继承
10.7 C++标准库异常类 层次结构
10.1 异常的概念
在编制程序时有一条惯例:把正常执行的程序与异常处理两部分分隔开 来,这样使代码更易于跟随和维护。在上例中,我们可以把两个try块 合成一个,而把两个catch子句都放在函数最后。
10.2 异常处理的机制
在C++中建立异常抛出与异常处理之间有一整套程序设计的机制。 首先采用关键字try,构成一个try块(try block),它包含了抛 出异常的语句。当然也可以是包含了这样的调用语句,该语句所 调用的函数中有能够抛出异常的语句。
请看下面的程序段给出try块与catch子句的关系: int main(){
本章介绍的技术,尽管是为大型软件工程开发所发展的,但是它在 标准C++中已经成为一个标准的技术,在任何规模的程序中都可以 使用。 C++提供了一些内置的语言特性来产生(raise)或抛出 (throw)异常,用以通知“异常已经发生”,然后由预先安排的 程序段来捕获(catch)异常,并对它进行处理。这种机制可以在 C++程序的两个无关(往往是独立开发)的部分进行“异常”通信。 由程序某一部分引发了另一部分的异常,这一异常可回到引起异常 的部分去处理(沿着程序函数的调用链)2 异常处理的机制
首先,在C++中异常往往用类(class)来实现,以栈为例,异常 类声明如下: class popOnEmpty{...}; //栈空异常 class pushOnFull{...}; //栈满异常
不再是一测到栈满或空就退出程序了,而是抛出一个异常。 template <typename T>void Stack<T>::Push(const T&data){
if(IsFull()) throw pushOnFull<T>(data); //注意加了括号,是构造一个无名对象 elements[++top]=data; } template<typename T>T Stack<T>::Pop(){ if(IsEmpty()) throw popOnEmpty<T>(); return elements[top--]; } 注意pushOnFull是类,C++要求抛出的必须是对象,所以必须有“()”, 即调用构造函数建立一个对象。异常并非总是类对象,throw表达式也可 以抛出任何类型的对象,如枚举、整数等等。但最常用的是类对象。 throw表达式抛出异常为异常处理的第一步。在堆栈的压栈和出栈操作中 发生错误而抛出的异常,理所当然地应由调用堆栈的程序来处理。
第十章 异常处理
大型和十分复杂的程序往往会产生一些很难查找的甚至是 无法避免的运行时错误。当发生运行时错误时,不能简单地结 束程序运行,而是退回到任务的起点,指出错误,并由用户决 定下一步工作。面向对象的异常处理(exception handling) 机制是C++语言用以解决这个问题的有力工具。
函数执行时,放在try(测试)程序块中的任何类型的数据对 象发生异常,都可被throw块抛出,随即沿调用链退回,直到 被catch块捕获,并在此执行异常处理,报告出现的异常等情 况。从抛出到捕获,应将各嵌套调用函数残存在栈中的自动 对象、自动变量和现场保护内容等进行清除。如果已退到入 口函数还未捕获则由abort()来终结入口函数。
int a[9]={1,2,3,4,5,6,7,8,9},b[9]={0},i; stack<int>istack(8); try{ for(i=0;i<9;i++) istack.Push(a[i]); istack.PrintStack(); } catch(pushOnFull<int>){cerr<<”栈满”<<endl;} try{ for(i=0;i<9;i++){b[i]=istack.Pop();} } catch(popOnEmpty<int>){cerr<<”栈空”<<endl;} for(i=0;i<9;i++) cout<<b[i]<<’\t’; cout<<endl; return 0; } 这里有两个try块,分别对应压栈与出栈;也有两个catch子句(catch clause),分别处理压栈时的栈满和出栈时的栈空。
这里所讲的异常(exception)是程序可能检测到 的,运行时不正常的情况,如存储空间耗尽、数组越 界、被0除等等,可以预见可能发生在什么地方,但 是无法确知怎样发生和何时发生。特别在一个大型的程序(软 件)中,程序各部分是由不同的小组编写的,它们由公共接口 连起来,错误可能就发生在相互的配合上,也可能发生在事先 根本想不到的个别的条件组合上。
10.2 异常处理的机制
由catch字句捕获并处理异常是第二步。注意与catch语句分别 匹配的是在压栈和出栈成员函数模板中的throw语句,一个抛出 pushOnFull类的无名对象,另一个抛出popOnEmpty类的无名 对象。
程序按下列规则控制: 1.如果没有异常发生,继续执行try块中的代码,与try块相关联 的catch子句被忽略,程序正常执行,main()返回0。 2.当第一个try块在for循环中抛出异常,则该for循环退出,try 块 也 退 出 , 去 执 行 pushOnFull 异 常 的 catch 子 句 。 istack.PrintStack()不再执行,被忽略。 3.如果第二个try块调用Pop()抛出异常,则退出for和try块,去 执行popOnEmpty异常的catch子句。 4.当某条语句抛出异常时,跟在该语句后面的语句将被跳过。程 序执行权交给处理异常的catch子句,如果没有catch子句能够处 理异常,则交给C++标准库中定义的terminate()。