1、异常处理,主讲教师:陈婷,18.1 异常的概念 18.2 异常的实现 18.3 异常的规则 18.4 默认异常处理 18.5 异常派生族系,本章内容,#include using namespace std; void divided(double a, double b) / 实现两个浮点数除法 double result = a/b; / 会不会有问题? coutab; divided(a, b); / 调用divided函数 return 0; ,18.1 异常的概念,Ch18_01,#include #include using namespace std; int main() ch
2、ar *ch; / 字符指针 long long size; coutsize; coutch; cout“String Size = ”strlen(ch)endl; delete ch; / 释放堆空间 return 0; ,18.1 异常的概念,Ch18_02,异常(Exception): 程序有时会遇到运行阶段错误,导致程序无法正常地运行下去。 例如: 程序试图打开一个不可用的文件 请求过多的内存 遭遇不能容忍的值 说明: 运行异常,可以预料,但不能避免,它是由系统运行环境造成的 程序要有能够解决这种运行异常的能力,18.1 异常的概念,异常处理机制,使用异常处理机制的步骤: 定义异常
3、。将那些有可能产生错误的语句框定在try语句块中。 定义异常处理(捕获异常)。将异常处理的语句放在catch语句块中,以便异常被传递过来时进行处理。 抛掷异常。检测是否产生异常,若是,则通过throw语句抛掷异常。,18.2 异常的实现,try语句:定义异常,catch语句:捕获异常,throw语句:抛掷异常,#include using namespace std; void divided(double a, double b) / 实现两个浮点数除法 double result; try / 定义异常 if(b=0.0) throw b; / 抛掷异常 result = a/b; cou
4、tab; divided(a, b); return 0; ,18.2 异常的实现,Ch18_03,说明: try语句块表示块中的语句可能会发生异常,放在其中加以监控。注意:C+只理会受监控的运行异常。 throw后面的表达式的类型被称为所引发的异常类型。 在try语句块之后必须紧跟一个或多个catch语句,目的是对发生的异常进行处理(注意:try之前不允许出现catch)。 catch( )括号中的声明只能容纳一个形参,当类型与抛掷异常的类型匹配时,该catch( )语句块便称捕获了一个异常而转到其块中进行异常处理。catch( )形参的值则为throw语句抛掷的异常值。 当异常发生时,tr
5、y语句块中异常之后的语句不再执行。,18.2 异常的实现,#include using namespace std; void divided(double a, double b) / 实现两个浮点数除法 double result; try / 定义异常 if(b=0.0) throw b; / 抛掷异常 result = a/b; coutab; divided(a, b); return 0; ,18.3 异常的规则,Ch18_04,C+只理会受监控的运行异常,#include using namespace std; int main() int idx; coutidx; try
6、/ 定义异常 if(idx=0) throw 10; / int型异常 else if(idx=1) throw 13.14; / double型异常 else if(idx=2) throw c; / char型异常 else throw “C+”; / 字符串异常 ,18.3 异常的规则,catch(int n) / 捕获int型异常 cout“Int Exception: ”nendl; catch(double d) / 捕获double型异常 cout“Double Exception: ”dendl; catch(char c) / 捕获char型异常 cout“Char Exce
7、ption: ”cendl; catch(char *s) / 捕获字符串异常 cout“String Exception: ”sendl; return 0; ,Ch18_05,寻找catch中的最佳匹配来进行异常处理,#include using namespace std; int main() int idx; coutidx; try / 定义异常 if(idx=0) throw 10; / int型异常 else if(idx=1) throw 13.14; / double型异常 else if(idx=2) throw c; / char型异常 else throw “C+”;
8、 / 字符串异常 ,18.3 异常的规则,catch(int) / 捕获int型异常 cout“Int Exception! ”endl; catch(double) / 捕获double型异常 cout“Double Exception! ”endl; catch(char) / 捕获char型异常 cout“Char Exception! ”endl; catch(char *) / 捕获字符串异常 cout“String Exception! ”endl; return 0; ,catch中的形参名可以省略,但类型不能省略,#include using namespace std; cl
9、ass CException ; / 类定义 int main() int idx; coutidx; try / 定义异常 if(idx=0) throw 10; / int型异常 else if(idx=1) throw 13.14; / double型异常 else if(idx=2) throw c; / char型异常 else if(idx=3) throw CException(); / 类异常,18.3 异常的规则,else throw “C+”; / 字符串异常 catch(int) / 捕获int型异常 cout“Int Exception! ”endl; catch(do
10、uble) / 捕获double型异常 cout“Double Exception! ”endl; catch(char) / 捕获char型异常 cout“Char Exception! ”endl; catch(CException) / 捕获类异常 cout“Class Exception! ”endl; return 0; ,当无匹配的catch进行异常处理时,系统调用默认异常处理程序abort( )来终止程序运行。,Ch18_06,#include using namespace std; class CException ; / 类定义 int main() int idx; co
11、utidx; try / 定义异常 if(idx=0) throw 10u; / unsigned int型异常 else if(idx=1) throw 13.14f; / float型异常 else if(idx=2) throw c; / char型异常 else throw CException(); / 类异常 ,18.3 异常的规则,catch(int) / 捕获int型异常 cout“Int Exception! ”endl; catch(double) / 捕获double型异常 cout“Double Exception! ”endl; catch(char) / 捕获cha
12、r型异常 cout“Char Exception! ”endl; catch(CException) / 捕获类异常 cout“Class Exception! ”endl; return 0; ,抛掷异常与异常处理程序之间是按数据类型严格匹配来捕获的,不允许类型转换。,Ch18_07,#include using namespace std; int main() double a, b, result; coutab; try / 定义异常 if(b=0.0) throw b; / 抛掷异常 result = a/b; catch(double) / 捕获、处理异常 coutb; resu
13、lt = a/b; catch(int) cout“Int Exception!”endl; / 捕获、处理异常 cout“a/b = ”resultendl; / catch块后的语句 return 0; ,18.3 异常的规则,Ch18_08,当catch分程序执行完毕时,则跟随最后一个catch分程序的代码就会被执行。,#include using namespace std; double divided(double a, double b) / 实现两个浮点数除法 if(b=0.0) throw b; / 抛出异常 return a/b; int main() try / 定义异常
14、 cout“13.14/2.0 = ”divided(13.14, 2.0)endl; cout“13.14/0.0 = ”divided(13.14, 0.0)endl; cout“13.14/3.0 = ”divided(13.14, 3.0)endl; catch(double) / 捕获异常 cout“Exception of dividing zero occurs!”endl; return 0; ,18.3 异常的规则,可以将抛掷异常与处理异常放在不同的函数中,#include using namespace std; class CException ; / 类定义 int m
15、ain() int idx; coutidx; try / 定义异常 if(idx=0) throw 10; / int型异常 else if(idx=1) throw 13.14; / double型异常 else if(idx=2) throw c; / char型异常 else if(idx=3) throw CException(); / 类异常 else throw “Exception”; / 字符串异常 ,18.4 默认异常处理,catch(int) / 捕获int型异常 cout“Int Exception! ”endl; catch(double) / 捕获double型异常
16、 cout“Double Exception! ”endl; catch(char) / 捕获char型异常 cout“Char Exception! ”endl; catch(CException) / 捕获类异常 cout“Class Exception! ”endl; catch() / 捕获所有其他异常 cout“Unexpected Exception!”endl; return 0; ,Ch18_09,#include using namespace std; class FileError ; / 异常基类 class IncorrectDirectory: public Fil
17、eError ; / 异常派生类 class IncorrectFormat: public FileError ; / 异常派生类 class FileCorruption: public FileError ; / 异常派生类 int main() int exception; cinexception; try / 定义异常 switch(exception) case 1: throw IncorrectDirectory(); break; / 抛掷派生类异常 case 2: throw IncorrectFormat(); break; / 抛掷派生类异常 case 3: thro
18、w FileCorruption(); break; / 抛掷派生类异常 case 4: throw FileError(); break; / 抛掷基类异常 default: throw “Unexpected”; break; / 抛掷字符串异常 ,18.5 异常派生族系,catch(FileError) / 捕获基类异常 cout“FileError Exception!”endl; catch(IncorrectDirectory) / 捕获派生类异常 cout“IncorrectDirectory Exception!”endl; catch(IncorrectFormat) / 捕
19、获派生类异常 cout“IncorrectFormat Exception!”endl; catch(FileCorruption) / 捕获派生类异常 cout“FileCorruption Exception!”endl; catch() / 捕获其他异常 cout“Unexpected Exception!”endl; return 0; ,18.5 异常派生族系,Ch18_10,为什么无法捕获派生类异常?,抛掷的派生类异常都被基类捕获了!,异常捕获的规则除了前面所说的,必须严格匹配数据类型外,对于类的派生,下列情况可以捕获异常: 异常处理的数据类型是公有基类(public继承),抛掷异
20、常的数据类型是派生类。 异常处理的数据类型是指向公有基类的指针,抛掷异常的数据类型是指向派生类的指针。 try / throw new IncorrectDirectory; catch(FileError *) / ,18.5 异常派生族系,#include using namespace std; class FileError ; / 异常基类 class IncorrectDirectory: public FileError ; / 异常派生类 class IncorrectFormat: public FileError ; / 异常派生类 class FileCorruption
21、: public FileError ; / 异常派生类 int main() int exception; cinexception; try switch(exception) case 1: throw IncorrectDirectory(); break; / 抛掷派生类异常 case 2: throw IncorrectFormat(); break; / 抛掷派生类异常 case 3: throw FileCorruption(); break; / 抛掷派生类异常 case 4: throw FileError(); break; / 抛掷基类异常 default: throw
22、 “Unexpected”; break; / 抛掷字符串异常 ,18.5 异常派生族系,正确异常处理方式,catch(IncorrectDirectory) / 捕获派生类异常 cout“IncorrectDirectory Exception!”endl; catch(IncorrectFormat) / 捕获派生类异常 cout“IncorrectFormat Exception!”endl; catch(FileCorruption) / 捕获派生类异常 cout“FileCorruption Exception!”endl; catch(FileError) / 捕获基类异常 cou
23、t“FileError Exception!”endl; catch() / 捕获其他异常 cout“Unexpected Exception!”endl; return 0; ,18.5 异常派生族系,将catch(基类)语句块总是放在catch(派生类)语句块的后面!,下列关于异常的叙述错误的是:A. 编译错属于异常,可以抛出 B. 运行错属于异常 C. 硬件故障也可当异常抛出 D. 只要是编程者认为是异常的都可当异常抛出,下列叙述错误的是: throw的操作数表示异常类型 B.throw的操作数值可以区别不同的异常 C. throw抛出不同异常时需要用不同的操作数类型来区分 D. throw语句抛出的异常可以不被捕获,下列叙述错误的是: A. catch()语句可捕获所有类型的异常 B.一个try语句可以有多个catch语句 C.catch()语句可以放在catch语句组的前面 D.程序中try语句与catch语句是一个整体,缺一不可,下列程序运行结果为: class Apublic:A( )cout“A“n“; ;char fun0() A A1;throw(E);return 0;,int main()trycoutfun0()“n“;catch(char c) coutc“n“;return 0;,A. AEB.0AEC.0E D.E,