异常处理
返回首页
图11-1 异常处理示意图
返回本节
11.3 异常处理的实现
11.3.1 异常处理的语法 11.3.2 异常处理机制
返回首页
C++语言异常处理机制的基本思想是将异常的检 语言异常处理机制的基本思想是将异常的检 测与处理分离。 测与处理分离 。 当在一个函数体中检测到异常 条件存在, 但无法确定相应的处理方法时, 条件存在 , 但无法确定相应的处理方法时 , 将 引发一个异常, 引发一个异常 , 并由函数的直接或间接调用检 测并处理这个异常。这一基本思想用3个保留字 测并处理这个异常。这一基本思想用 个保留字 实现: 实现:throw、try和catch。其作用是: 、 和 。其作用是: (1)try:标识程序中异常语句块的开始。 ) :标识程序中异常语句块的开始。 ( 2) throw: 用来创建用户自定义类型的异常 ) : 错误。 错误。 (3)catch:标识异常错误处理模块的开始。 ) :标识异常错误处理模块的开始。
有成员函数Reason()用来显示异常 例11-3:定义一个异常类 :定义一个异常类CException,有成员函数 有成员函数 用来显示异常 的类型, 定义函数fun()触发异常 , 在主函数的try模块中调用 的类型 , 定义函数 触发异常, 在主函数的 模块中调用fun(), 在 , 触发异常 模块中调用 catch模块中捕获异常,观察程序的执行过程。 模块中捕获异常, 模块中捕获异常 观察程序的执行过程。 #include <iostream.h> class CException { public: CException(){} ~CException(){} const char *Reason() const {return "CException 类中的异 常。";} }; void fun() {
返回首页
11.2 异常处理的基本思想
异常的基本思想是: 异常的基本思想是: ( 1)实际的资源分配通常在程序的低层进行 , 如上图 ) 实际的资源分配通常在程序的低层进行, 中的F3()。 中的 。 (2) 当操作失败 、 无法分配内存或无法打开一个文件 ) 当操作失败、 在逻辑上如何进行处理通常在程序的高层, 时,在逻辑上如何进行处理通常在程序的高层,如上图 中的F1(),中间还可能有与用户的对话。 中的 ,中间还可能有与用户的对话。 ( 3)异常为从分配资源的代码转向处理错误状态的代 ) 码提供了一种表达方式。如果还存在中间层次的函数, 码提供了一种表达方式。如果还存在中间层次的函数, 如上图中的F2(),则为它们释放所分配的内存提供了机 如上图中的 , 但这并不包括传递错误状态信息的代码。 会,但这并不包括传递错误状态信息的代码。
返回本节
11.3.2 异常处理机制
分程序必须出现在前, 紧跟出现在后。 ( 1) try分程序必须出现在前 , catch紧跟出现在后 。 ) 分程序必须出现在前 紧跟出现在后 catch之后的圆括号中必须含有数据类型 , 捕获是利用 之后的圆括号中必须含有数据类型, 之后的圆括号中必须含有数据类型 数据类型匹配实现的。 数据类型匹配实现的。 ( 2)如果程序内有多个异常错误处理模块 , 则当异常 ) 如果程序内有多个异常错误处理模块, 错误发生时, 错误发生时,系统自动查找与该异常错误类型相匹配的 catch模块,查找次序为 模块, 出现的次序。 模块 查找次序为catch出现的次序。 出现的次序 的类, ( 3) 如果异常错误类型为 ) 如果异常错误类型为C++的类 , 并且该类有其基 的类 则应该将派生类的错误处理程序放在前面, 类,则应该将派生类的错误处理程序放在前面,基类的 错误处理程序放在后面。 错误处理程序放在后面。 ( 4)如果一个异常错误发生后 , 系统找不到一个与该 ) 如果一个异常错误发生后, 错误类型相匹配的异常错误处理模块, 错误类型相匹配的异常错误处理模块,则调用预定义的 运行时刻终止函数,默认情况下是abort。 运行时刻终止函数,默认情况下是 。
cout<<"Some other exception occurred."; cout<<endl; } } 此程序的运行结果为: 此程序的运行结果为: Now call Excp function. Creating a Demo object. Excp function throwing an exception! Deleting Demo object. An Ex exception occurred.
catch(类型1 参数 ) (类型 参数1) { //针对类型 的异常处理 针对类型1的异常处理 针对类型 } catch (类型 类型2 参数 ) 参数2) { //针对类型 的异常处理 针对类型2的异常处理 针对类型 } … catch (类型 类型n 参数 ) 参数n) { //针对类型 的异常处理 针对类型n的异常处理 针对类型 }
try子句后的复合语句是代码的保护段 。 如果预 子句后的复合语句是代码的保护段。 子句后的复合语句是代码的保护段 料某段程序代码( 或对某个函数的调用) 料某段程序代码 ( 或对某个函数的调用 ) 有可 能发生异常, 就将它放在try子句之后 子句之后。 能发生异常 , 就将它放在 子句之后 。 如果这 段代码( 或被调函数) 段代码 ( 或被调函数 ) 运行时真的遇到异常情 其中的throw表达式就会抛掷这个异常。 表达式就会抛掷这个异常。 况,其中的 表达式就会抛掷这个异常 catch子句后的复合语句是异常处理程序,“ 捕 子句后的复合语句是异常处理程序, 子句后的复合语句是异常处理程序 处理) 表达式抛掷的异常。 获”(处理)由throw表达式抛掷的异常。异常 表达式抛掷的异常 类型说明部分指明该子句处理的异常的类型, 类型说明部分指明该子句处理的异常的类型 , 它与函数的形参是类似的, 它与函数的形参是类似的 , 可以是某个类型的 也可以是引用。 值,也可以是引用。
cout<<"Createing a Demo object."<<endl; } ~Demo() //析构函数 析构函数 { cout<<"Deleting Demo object."<<endl; } }; void Excp() {
Demo A; //定义一个对象 定义一个对象 cout<<"Excp function throwing an exception!"; cout<<endl; throw Ex(); //创建成一个异常 创建成一个异常 } void main() { try { cout<<"Now call Excp function."<<endl; Excp(); } catch(Ex a) //捕捉 类异常 捕捉Ex类异常 捕捉 { cout<<"An Ex exception occurred."<<endl; } catch(...) {
cout<<"在catch模块中, 捕获到 在 模块中, 类型异常: 模块中 捕获到CException类型异常: 类型异常 "; cout<<E.Reason()<<endl; } catch(char *str) { cout<<"捕获到其他类型异常:"<<str<<endl; 捕获到其他类型异常: 捕获到其他类型异常 } cout<<"回到主函数,异常已被处理。"<<endl; 回到主函数, 回到主函数 异常已被处理。 }
(4)如果匹配的处理器未找到,则函数 terminate将被自动调用 , 而函数 将被自动调用, 将被自动调用 而函数terminate的 的 默认功能是调用abort终止程序。 终止程序。 默认功能是调用 终止程序 处理程序, ( 5) 如果找到了一个匹配的 ) 如果找到了一个匹配的catch处理程序 , 处理程序 且它通过值进行捕获, 且它通过值进行捕获 , 则其形参通过拷贝异常 对象进行初始化。 对象进行初始化。
第11章 异常处理 章
11.1 11.2 11.3 11.4 11.5 11.6 异常处理概述 异常处理的基本思想 异常处理的实现 标准C++库中的异常类 标准 库中的异常类 多路捕获 含有异常的程序设计
11.1 异常处理概述
程序可能按编程者的意愿终止, 程序可能按编程者的意愿终止,也可能因为程序中发生 了错误而终止。 了错误而终止。 程序的错误有两种,一种是编译错误,即语法错误。 程序的错误有两种,一种是编译错误,即语法错误。如 果使用了错误的语法、函数、结构和类, 果使用了错误的语法、函数、结构和类,程序就无法被 生成运行代码。另一种是在运行时发生的错误, 生成运行代码。另一种是在运行时发生的错误,它分为 不可预料的逻辑错误和可以预料的运行异常。 不可预料的逻辑错误和可以预料的运行异常。 异常处理机制是用于管理程序运行期间错误的一种结构 化方法。 化方法。所谓结构化是指程序的控制不会由于产生异常 而随意跳转。 而随意跳转。异常处理机制将程序中的正常处理代码与 异常处理代码显式区别开来,提高了程序的可读性。 异常处理代码显式区别开来,提高了程序的可读性。
11.3.1 异常处理的语法
程序中, 在C++程序中,任何需要检测异常的语句(包括 程序中 任何需要检测异常的语句( 函数调用)都必须在try语句块中执行 语句块中执行, 函数调用)都必须在 语句块中执行,异常必 须由紧跟在try语句后面的 语句后面的catch语句来捕获并处 须由紧跟在 语句后面的 语句来捕获并处 理。因而,try与catch总是结合使用。throw、 因而, 与 总是结合使用。 、 总是结合使用 try和catch语句的一般语法如下: 语句的一般语法如下: 和 语句的一般语法如下 throw <表达式 表达式>; 表达式 try { //try语句块 语句块 }