首页 理论教育 异常处理详解:C++STL异常类型与catch顺序

异常处理详解:C++STL异常类型与catch顺序

时间:2023-10-25 理论教育 版权反馈
【摘要】:检测与处理之间的联系依靠“异常类型”。catch子句按其在try块后出现的顺序被匹配之后,catch块将其捕获并处理异常。10)至少需要有一个程序处理所有其他针对处理的异常。15)析构函数退出之后,不允许还有未处理的异常。

异常处理详解:C++STL异常类型与catch顺序

异常处理的基本思想是简化程序的错误代码,为程序鲁棒性提供一个标准检测机制。前面章节已经讲述:C++通过使用throw关键字产生异常,使用try关键字定义需要检测的程序块,使用catch关键字来捕获异常以及填写异常处理的代码;异常通常是由一个确定类或派生类的对象产生;C++能释放堆栈,并可清除堆栈中的所有对象。

本节将详细讲述异常的处理、异常的声明以及异常的访问。

对于可预料但不可避免的程序错误,不能任其发生并无所作为,要将消极的等待变为积极预防,还要将预防的处理内容归纳整理,分门别类地做成类。不能仅凭编程经验,而是要凭借人人均掌握的规范,实现圆满的处理。通常,规范是指在函数处理过程中设置陷阱,异常一旦触发,必然会被异常处理所收纳,最终实现统一归口处理。

前面已经讲过,异常处理有3种方式:

1)在出现异常时,直接调用abort()或者exit()函数。

2)通过函数的返回值来判断异常;如果函数包含有多个返回值,会浪费不必要的时间开销。

3)通过try()-catch()函数的结构化异常处理而完成。

1.异常处理的实现机制

异常处理的实现离不开3个关键字:throw、try和catch。抛掷异常是在特定的函数中,try块应该包含该函数,catch块根据不同的情况进行相应的处理。其形式大致如下:

前面章节给出了很多较详细的例子。此处再提供一例。

例8-5

例8-5的执行结果为:

2.异常处理语句的语法

throw、try和catch3个关键字分工明确,各司其职。throw负责发现异常,并抛出异常对象;如果将其放在函数声明中,又被称为异常接口声明。try负责设置一个侦错范围(又叫保护段)。try的作用其实是划定一个跳跃的边界。catch负责处理捕获的异常,所抛出的异常对象并非建立在函数栈上,而是建在专用的异常栈上,可以跨越函数而传递给上层。读者请注意以下条目:

•每个catch()相当于一段函数代码。

•每个throw则相当于一个函数调用

•每个try块至少跟一个catch()。

•每个程序可设置个数不定的try、throw和catch。只有逻辑上的呼应,而无数量上的对应关系,且不受所在函数模块限制。

•异常抛出点往往距异常捕获点很远,可以不在同层模块中。

•甚至有的throw不明确,可能来自于系统函数或标准库中。

•try块可以并列,可以嵌套

3.异常处理不唤醒

在try保护段代码执行期间,一旦发生异常,则立即抛出,并由相应的catch子句捕获处理。“抛出”和“捕获”之间的代码被越过,不会被执行。程序从try块之后跟随的最后一个catch块子句后面的语句继续执行。

通俗地讲,异常处理是将检测与处理分离,以便各司其职,灵活搭配工作。检测与处理之间的联系依靠“异常类型”。异常通过throw创建一个异常对象并抛出。可能抛出异常的程序段嵌在try块中,按正常的顺序执行到达try语句时,会执行try块内的保护段。如果在保护段执行期间没有引起异常,那么在try块之后的catch子句将不被执行。程序会从try块后最后一个catch子句后面的语句继续执行。catch子句按其在try块后出现的顺序被匹配之后,catch块将其捕获并处理异常。

如果没有找到匹配的处理器,terminate()函数会被调用,其默认功能是调用abort()函数并终止程序。(www.xing528.com)

4.函数声明

关键字throw还可以用于函数声明。前面章节已经有过介绍。例如,

在函数声明时,若带有throw关键字,则在函数定义时必须同样出现。例如,

5.使用异常

“什么时候使用异常?”这是很难回答的问题。

首先,不能使用异常完全代替返回值。因为返回值的含义不一定只是成功或失败,可能会是一个选择的状态。

其次,在特定情况下,异常能否发挥它的优点(该优点恰好是不能使用其他技术实现的)。

异常还有如下一些规则:

1)异常机制只能用于处理错误。

2)通常不要使用goto语句或switch语句跳转至try块或catch块内。

3)不要显式地抛出NULL。

4)若在函数声明时指定了具体的异常类型,则只能抛出该指定类型的异常。

5)若在函数声明时设定了异常类型,则在编译单元中该函数的声明必须有同样的设定。

6)异常只能在初始化之后,程序结束之前抛出。

7)throw语句本身不允许引发新的异常。

8)空的throw语句只能出现在catch语句块中。

9)所有流程中显示的抛出异常应该有一个类型兼容的处理程序。

10)至少需要有一个程序处理所有其他针对处理的异常。

11)若try-catch语句块中包含多个处理程序,或派生类和部分或全部基类的function- try-block块有多个处理程序,则处理程序的顺序应该是先派生类后基类。

12)如果try-catch语句块或者function-try-block块有多个处理程序,catch(…)处理程序(捕获所有其他异常)应该放在最后。

13)若异常对象为类的对象,则应通过引用来捕获。

14)若构造函数和析构函数是function-try-block结构,则在catch处理程序中不能引用该类或其基类的非静态成员。

15)析构函数退出之后,不允许还有未处理的异常。

免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。

我要反馈