Presentation is loading. Please wait.

Presentation is loading. Please wait.

第12章 异常处理 C++自身有着非常强的纠错能力,发展到如今,已经建立了比较完善的异常处理机制. C++的异常情况无非两种,一种是语法错误,即程序中出现了错误的语句、函数结构和类,致使编译程序无法进行。另一种是运行时发生的错误,一般与算法有关。 关于语法错误, C++编译器的报错机制可以让我们轻松地解决这些错误;

Similar presentations


Presentation on theme: "第12章 异常处理 C++自身有着非常强的纠错能力,发展到如今,已经建立了比较完善的异常处理机制. C++的异常情况无非两种,一种是语法错误,即程序中出现了错误的语句、函数结构和类,致使编译程序无法进行。另一种是运行时发生的错误,一般与算法有关。 关于语法错误, C++编译器的报错机制可以让我们轻松地解决这些错误;"— Presentation transcript:

1 第12章 异常处理 C++自身有着非常强的纠错能力,发展到如今,已经建立了比较完善的异常处理机制. C++的异常情况无非两种,一种是语法错误,即程序中出现了错误的语句、函数结构和类,致使编译程序无法进行。另一种是运行时发生的错误,一般与算法有关。 关于语法错误, C++编译器的报错机制可以让我们轻松地解决这些错误;

2 异常(exception)——程序运行期出现的问题或错误。
异常处理——结构化的处理异常的方法,在有可能发生异常的地方做出预见性的安排。 第二种是运行时的错误,常见的有文件打开失败、数组下标溢出、系统内存不足等等。而一旦出现这些问题,引发算法失效、程序运行时无故停止等故障也是常有的。这就要求我们在设计软件算法时要全面。比如针对文件打开失败的情况,保护的方法有很多种,最简单的就是使用“return”命令,告诉上层调用者函数执行失败;另外一种处理策略就是利用c++的异常机制,抛出异常。

3 代码有问题吗?如果有怎样去处理 通过这里例子引出传统的程序运行是错误处理方式, 即if判断 然后返回,程序结束。 传统的异常处理方式很不灵活,也不方便。

4 用 exit () 、 return ()或assert()运行期错误处理机制,具有“一个入口,多个出口”的特点,一旦检测到异常,程序崩溃。
非结构化异常处理: 用 exit () 、 return ()或assert()运行期错误处理机制,具有“一个入口,多个出口”的特点,一旦检测到异常,程序崩溃。 结构化的异常处理: 积极的运行期问题处理机制。当异常出现后,可按“警告—忽略”、“对话—补救”或安全退出等模式,使程序可以在对运行条件做出适当安排或改善后继续运行下去。 一个大的系统那个中,包含许多模块,每个模块又包含很多函数,函数之间又相互调用,比较复杂。如果在每一个函数中都设置处理异常的程序段,会使程序过于复杂和庞大。

5 12. 1 异常处理的基本语法 C++的异常处理的基本思想是将异常的检测与处理分离。
在一个函数体中检测到异常条件满足,但无法确定相应的处理方法时,就引发一个异常,然后由函数的直接或间接调用者处理此异常。 因此,如果在执行一个函数过程中,出现异常,可以不在本函数中立即处理,而是抛出一个异常,传给它的上一级(即调用它的函数),它的上级可以选择处理该异常,或者再往它的上级传递,如此逐级上升,如果最高一级还是无法处理,就调用系统函数terminate,使程序终止运行。

6 C++的异常处理建立在三个关键字基础之上:
try 、catch和throw。 在C++中,其采用throw语句来实现,如果检测到产生异常,则抛出异常。如果在try语句块的程序段中(包括在其中调用的函数)发现了异常,且抛弃了该异常,则这个异常就可以被try语句块后的某个catch语句所捕获并处理,捕获和处理的条件是被抛弃的异常的类型与catch语句的异常类型相匹配。

7 以抛出对象来触发异常 C++异常处理语句的一般形式如下: try{ //try 块内监视异常
if (条件)throw exception; //由throw 抛出异常 …; //其它语句 } catch( 类型1 参数1 ){ //catch块内处理代码 catch( 类型2 参数2 ){ …; …… catch( 类型n 参数n ){ 以抛出对象来触发异常 本章重点语法 注意:C++通过try夺取运行期的环境控制权,异常的引发是由程序员控制的,而不是由程序编译器控制的。任何要检测异常的语句或函数调用都必须在try语句块中执行。异常由离try块最近的相应的catch语句来捕获并处理。

8 例12.1 异常处理演示。 void main() { invoke(0); invoke(1); invoke(2);
} 例12.1 异常处理演示。 #include<iostream.h> const double PI=3.1416; void invoke(int x) { try{ if(x==0) throw x+5; //抛出int型的异常 if(x==1) throw 'A'; //抛出cahr型的异常 if(x==2) throw "An apple"; //抛出字符串型的异常 if(x==3) throw PI; //抛出double型的异常 } catch(int i) { cout<<"catch a integer "<<i<<endl; } catch(char c) { cout<<"catch a char "<<c<<endl; } catch(char str[10]) { cout<<"catch a string "<<str<<endl; } catch(double d) { cout<<"catch a double "<<d<<endl; } 通过这个例子讲解 try throw and catch 如何工作 程序运行结果: catch a integer 5 catch a char A catch a string An apple catch a double

9 编写异常处理代码的规则: (1) 可以有数量不限的catch处理程序出现在try块之后,在try 块出现之前不能出现 catch块。

10 编写异常处理代码的规则: (2) 在关键字catch之后的圆括号内应包括数据和类型声明。因为捕获是根据throw exception 语句的异常类型与之匹配来实现的,它与一般函数的作用相似。如果在编写异常处理程序的函数带有参数,参数名仍可以传入catch 处理程序中。 catch 语法 注意和对象声明区别和联系

11 (3) 如果抛出一个异常,而在通往抛出函数的调用链中找不到与之匹配的catch处理程序,运行将以调用系统 terminate() 异常退出。
编写异常处理代码的规则: (3) 如果抛出一个异常,而在通往抛出函数的调用链中找不到与之匹配的catch处理程序,运行将以调用系统 terminate() 异常退出。 异常抛出后的处理机制

12 (4) 如果catch中处理程序执行完毕,而无返回或终止指令,将跳过后面的catch块继续执行程序。
编写异常处理代码的规则: (4) 如果catch中处理程序执行完毕,而无返回或终止指令,将跳过后面的catch块继续执行程序。

13 (5) 如果throw语句没有被执行,那么catch块将被忽略。
编写异常处理代码的规则: (5) 如果throw语句没有被执行,那么catch块将被忽略。 (6) 在实际运用中,throw执行前一定有一个条件判断。 这个判断条件非常关键,考察程序的健壮性

14 编写异常处理代码的规则: (7) throw 抛出的可以是一个常量,也可以是一个变量。关键字throw 还可以灵活地放到很多地方,只要try块中的语句能直接或间接地执行到它。

15 编写异常处理代码的规则: (8) catch在比较类型匹配时并不需要完全相同。被throw抛出的异常的数据类型与catch 处理程序的参数类型进行匹配的过程, 由精确匹配和自动数据类型转换的匹配组成。 在下列情况视为两者类型匹配: catch的参数类型与抛出异常严格匹配、 catch的参数类型是被抛出异常所在类的公有基类、 catch的参数类型是指向派生类的指针。 异常类型匹配, 回忆参数传递的匹配,模板参数的匹配知识

16 12. 2 异常捕获 单路捕获 单路捕获就是在程序中使用一个catch处理语句来捕获错误。这种处理比较简单。当C++异常处理语句一般格式式中 n=1 时,就是单路捕获。

17 例12.2 使用try…throw…catch编写一异常处理函数,对下列程序进行异常处理。
#include <iostream.h> #include <string.h> class CRange{ int x; public: CRange(int a){x=a;} int get_x(){return x;} }; class Range: public CRange{ Range(int b):CRange(b){};

18 class String{ char *contents; int length; public: String(char *str) { length=strlen(str); contents=new char[length+1]; strcpy(contents,str); } char& operator [](int j) { Range R(100); if(j>=0 && j<length) return contents[j]; throw R; } void print(String &s) { int j; for(j=0;j<20;j++) cout<<s[j]<<" "; cout<<endl; } };

19 int function(String &ss)
{ try{ ss.print(ss); } catch(CRange cr){ cout<<endl<<"Out of rangle!"<<endl; return cr.get_x(); return 0; void main() String x("abc"); int j=function(x); cout<<"function() returns: "<<j<<end;; 程序输出: a b c Out of rangle! function() returns: 100 (1) 由于在String类中重载了运算符[],重载函数又调用throw语句,故在函数print()中运行for 循环的s[j]时将会遇到异常抛出,根据条件在循环3次后将抛出异常。 (2) Range类的异常被function()函数中的catch捕获,是由于catch的参数类型CRange为Range的公有基类。

20 多路捕获 当C++异常处理语句格式中 n大于1时, 就构成多路捕获结构。多路捕获使得程序在出现一个异常时,可以由相应的处理程序进行有针对性的处理。多路捕获的异常处理比单路捕获更灵活,适用面更广.

21 多路捕获的一般规则: (1) 如果try块中的一个语句或者在try 块的一个被调函数中的一个语句抛出一个异常,在沿着调用返回时该异常到达第一个catch语句,逐个查看每个catch语句处理程序,根据被抛对象,找出匹配。注意,处理程序有一定的先后顺序。 注意: catch(...){ } 捕获任何类型的异常

22 多路捕获的一般规则: (2) 如果找到一个匹配,就执行匹配的处理程序代码。如果没有找到匹配,则检查下一个catch语句, 若所有的catch语句都找完了,还没有找到匹配的catch语句,就由调 用系统函数terminate()终止调用,后者按常规再调用abort0。

23 STL 提供的标准Exceptions C++的标准库提供了一个异常类的层次结构,在预定义的异常层次结构中,错误被分成两类:一是逻辑错误,由于程序内部逻辑而导致的错误,二是运行时错误,由于程序之外的某种事件而导致的错误 建议使用STL中提供的异常处理机制

24 STL 提供的标准Exceptions 标准STL异常例子讲解,是同学们了解如何使用

25 前面例子如何用异常处理方式进行改进


Download ppt "第12章 异常处理 C++自身有着非常强的纠错能力,发展到如今,已经建立了比较完善的异常处理机制. C++的异常情况无非两种,一种是语法错误,即程序中出现了错误的语句、函数结构和类,致使编译程序无法进行。另一种是运行时发生的错误,一般与算法有关。 关于语法错误, C++编译器的报错机制可以让我们轻松地解决这些错误;"

Similar presentations


Ads by Google