第16章异常处理 16.1异常处理概述 162异常处理的基本思想 16.3C++异常处理的实现 164标准C++库中的异常类 16.5多路捕获 166含有异常的程序设让
第16章 异常处理 16.1 异常处理概述 16.2 异常处理的基本思想 16.3 C++异常处理的实现 16.4 标准C++库中的异常类 16.5 多路捕获 16.6 含有异常的程序设计
在编写程序时,应该考虑确定程序可能出 现的错误,然后加入处理错误的代码。也就是 说,在环境条件出现异常情况下,不会轻易出 现死机和灾难性的后果,而应有正确合理的表 现。这就是异常处理。C++提供了异常处理机 制,它使得程序出现错误时,力争做到允许用 户排除环境错误,继续运行程序
在编写程序时,应该考虑确定程序可能出 现的错误,然后加入处理错误的代码。也就是 说,在环境条件出现异常情况下,不会轻易出 现死机和灾难性的后果,而应有正确合理的表 现。这就是异常处理。C++提供了异常处理机 制,它使得程序出现错误时,力争做到允许用 户排除环境错误,继续运行程序
16.1异常处理概述 程序可能按编程者的意愿终止,也可能因为程序 中发生了错误而终止。例如,程序执行时遇到除数为0 或下标越界,这时将产生系统中断,从而导致正在执 行的程序提前终止 程序的错误有两种,一种是编译错误,即语法错 误。如果使用了错误的语法、函数、结构和类,程序 就无法被生成运行代码。另一种是在运行时发生的错 误,它分为不可预料的逻辑错误和可以预料的运行异 常
16.1 异常处理概述 程序可能按编程者的意愿终止,也可能因为程序 中发生了错误而终止。例如,程序执行时遇到除数为0 或下标越界,这时将产生系统中断,从而导致正在执 行的程序提前终止。 程序的错误有两种,一种是编译错误,即语法错 误。如果使用了错误的语法、函数、结构和类,程序 就无法被生成运行代码。另一种是在运行时发生的错 误,它分为不可预料的逻辑错误和可以预料的运行异 常
为处理可预料的错误,常用的典型方法是让被调 用函数返回某一个特别的值(或将某个按引用调用传 递的参数设置为一个特别的值),而外层的调用程序 则检查这个错误标志,从而确定是否产生了某一类型 的错误。另一种典型方法是当错误发生时跳出当前的 函数体,控制转向某个专门的错误处理程序,从而中 断正常的控制流。这两种方法都是权宜之计,不能形 成强有力的结构化异常处理模式。 异常处理机制是用于管理程序运行期间错误的 种结构化方法。所谓结构化是指程序的控制不会由于 产生异常而随意跳转。异常处理机制将程序中的正常 处理代码与异常处理代码显式区别开来,提高了程序 的可读性
为处理可预料的错误,常用的典型方法是让被调 用函数返回某一个特别的值(或将某个按引用调用传 递的参数设置为一个特别的值),而外层的调用程序 则检查这个错误标志,从而确定是否产生了某一类型 的错误。另一种典型方法是当错误发生时跳出当前的 函数体,控制转向某个专门的错误处理程序,从而中 断正常的控制流。这两种方法都是权宜之计,不能形 成强有力的结构化异常处理模式。 异常处理机制是用于管理程序运行期间错误的一 种结构化方法。所谓结构化是指程序的控制不会由于 产生异常而随意跳转。异常处理机制将程序中的正常 处理代码与异常处理代码显式区别开来,提高了程序 的可读性
162异常处理的基本思想 对于中小型程序,一旦发生异常,一般是将程序 立即中断执行,从而无条件释放系统所有资源。而对 于比较大的程序来说,如果出现异常,应该允许恢复 和继续执行。恢复的过程就是把产生异常所造成的恶 劣影响去掉,中间一般要涉及一系列的函数调用链的 退栈,对象的析构,资源的释放等。继续运行就是异 常处理之后,在紧接着异常处理的代码区域中继续运 行
16.2 异常处理的基本思想 对于中小型程序,一旦发生异常,一般是将程序 立即中断执行,从而无条件释放系统所有资源。而对 于比较大的程序来说,如果出现异常,应该允许恢复 和继续执行。恢复的过程就是把产生异常所造成的恶 劣影响去掉,中间一般要涉及一系列的函数调用链的 退栈,对象的析构,资源的释放等。继续运行就是异 常处理之后,在紧接着异常处理的代码区域中继续运 行
16.3C++异常处理的实现 C++语言异常处理机制的基本思想是将异常的检测 与处理分离。当在一个函数体中检测到异常条件存在, 但无法确定相应的处理方法时,将引发一个异常,并 由函数的直接或间接调用检测并处理这个异常。这 基本思想用3个保留字实现:thow、try和 catch。其作 用是 (1)ty:标识程序中异常语句块的开始 (2) throw:用来创建用户自定义类型的异常错 误 (3) catch:标识异常错误处理模块的开始
16.3 C++异常处理的实现 C++语言异常处理机制的基本思想是将异常的检测 与处理分离。当在一个函数体中检测到异常条件存在, 但无法确定相应的处理方法时,将引发一个异常,并 由函数的直接或间接调用检测并处理这个异常。这一 基本思想用3个保留字实现:throw、try和catch。其作 用是: (1)try:标识程序中异常语句块的开始。 (2)throw:用来创建用户自定义类型的异常错 误。 (3)catch:标识异常错误处理模块的开始
在一般情况下,被调用函数直接检测到异常条件 的存在并使用 throw引发一个异常(注意,C++语言的 异常是由程序员控制引发的,而不是由计算机硬件或 程序运行环境控制的);在上层调用函数中使用try检 测函数调用是否引发异常,检测到的各种异常由 catch 捕获并作相应处理 1631异常处理的语法 在C+程序中,任何需要检测异常的语句(包括函 数调用)都必须在try语句块中执行,异常必须由紧跟 着ty语句后面的 Icatch语句来捕获并处理。因而,try与 catch总是结合使用。 throw、ty和 Icatch语句的一般语法 如下:
在一般情况下,被调用函数直接检测到异常条件 的存在并使用throw引发一个异常(注意,C++语言的 异常是由程序员控制引发的,而不是由计算机硬件或 程序运行环境控制的);在上层调用函数中使用try检 测函数调用是否引发异常,检测到的各种异常由catch 捕获并作相应处理。 16.3.1 异常处理的语法 在C++程序中,任何需要检测异常的语句(包括函 数调用)都必须在try语句块中执行,异常必须由紧跟 着try语句后面的catch语句来捕获并处理。因而,try与 catch总是结合使用。throw、try和catch语句的一般语法 如下:
throw try /try语句块 catch(类型1参数1) 针对类型1的异常处理 catch(类型2参数2) /l对类型2的异常处理 catch(类型n参数n) /对类型n的异常处理
throw ; try { //try语句块 } catch(类型1 参数1) { //针对类型1的异常处理 } catch (类型2 参数2) { //针对类型2的异常处理 } … catch (类型n 参数n) { //针对类型n的异常处理 }
异常处理的执行过程如下: (1)控制通过正常的顺序执行到达try语句,然后 执行ty块内的保护段 (2)如果在保护段执行期间没有引起异常,那么 跟在try块后的 catch-子句就不执行,程序从异常被抛掷 的ty块后跟随的最后一个 catch-子句后面的语句继续执 行下去。 (3)如果在保护段执行期间或在保护段调用的任 何函数中有异常被抛掷,则从通过 throw运算数创建的 对象中创建一个异常对象。编译器从能够处理抛掷类 型的异常的更高执行上下文中寻找一个 catch子句(或 个能处理任何类型异常的 catch处理程序)。 catch处 理程序按其在ty块后出现的顺序被检查。如果没有找 到合适的处理程序,则继续检查下一个动态封闭的tr 块。此处理继续下去直到最外层的封闭try块被检查完
(1)控制通过正常的顺序执行到达try语句,然后 执行try块内的保护段。 (2)如果在保护段执行期间没有引起异常,那么 跟在try块后的catch子句就不执行,程序从异常被抛掷 的try块后跟随的最后一个catch子句后面的语句继续执 行下去。 (3)如果在保护段执行期间或在保护段调用的任 何函数中有异常被抛掷,则从通过throw运算数创建的 对象中创建一个异常对象。编译器从能够处理抛掷类 型的异常的更高执行上下文中寻找一个catch子句(或 一个能处理任何类型异常的catch处理程序)。catch处 理程序按其在try块后出现的顺序被检查。如果没有找 到合适的处理程序,则继续检查下一个动态封闭的try 块。此处理继续下去直到最外层的封闭try块被检查完。 异常处理的执行过程如下:
(4)如果匹配的处理器未找到,则运行函数 terminate将被自动调用,而函数 terminate的默认功能是 调用 abort终止程序 (5)如果找到了一个匹配的 catch处理程序,且它 通过值进行捕获,则其形参通过拷贝异常对象进行初 始化。如果它通过引用进行捕获,则参量初始化为指 向异常对象。在形参被初始化之后,开始“循环展开 栈”的过程,这包括对那些在与 catch处理器相对应的 try块开始和异常丢弃地点之间创建的(但尚未析构的) 所有自动对象的析构。析构以与构造相反的顺序进行 然后执行 catch处理程序,接下来程序跳转到跟随在最 后处理程序之后的语句。 注意: catch处理程序的出现顺序很重要,因为在 个ty块中,异常处理程序是按照它出现的顺序被检 查的
(4)如果匹配的处理器未找到,则运行函数 terminate将被自动调用,而函数terminate的默认功能是 调用abort终止程序。 (5)如果找到了一个匹配的catch处理程序,且它 通过值进行捕获,则其形参通过拷贝异常对象进行初 始化。如果它通过引用进行捕获,则参量初始化为指 向异常对象。在形参被初始化之后,开始“循环展开 栈”的过程,这包括对那些在与catch处理器相对应的 try块开始和异常丢弃地点之间创建的(但尚未析构的) 所有自动对象的析构。析构以与构造相反的顺序进行。 然后执行catch处理程序,接下来程序跳转到跟随在最 后处理程序之后的语句。 注意:catch处理程序的出现顺序很重要,因为在 一个try块中,异常处理程序是按照它出现的顺序被检 查的