在异常捕获和处理过程中,有如下规则。
(1)多路捕获:依次匹配多个catch语句块。
(2)异常处理中的构造和析构:若catch语句中声明的形参是值类型,则会用throw表达式的值复制构造该形参对象。若catch语句中形参类型是引用类型,则无须调用复制构造函数,这是值得推荐的catch语句形式。在try语句块中定义的自动存储类对象或者变量在栈解退时,会被析构。
(3)捕获具有继承关系的异常类型:当多路catch语句中的异常类型具有继承关系时,要注意把捕获基类异常的catch语句块放在捕获派生类异常的catch语句块后面。
(4)捕获所有异常:catch(...)形式的语句块可以捕获所有类型的异常。
(5)重新抛出异常:在catch语句块中使用空throw语句,可以再次抛出该异常对象。
(6)异常规格说明:在函数声明部分显式指出该函数可能抛出的异常类型。
下面逐一举例说明这些规则:
▶5.7.2.1 多路捕获
异常处理程序通常放在catch块中,每个catch语句必须在圆括号中指明能够捕获异常的类型以及形参名称,然后在花括号中放置异常处理的程序代码。可以在try语句后面列出多个catch语句以捕获所有可能的异常类型。当有多个catch语句时,对它们的匹配是按照它们所在程序行的先后顺序进行的。
▶5.7.2.2 异常处理中的构造和析构
当异常发生时,为从异常抛出点把必要的错误信息传递到异常处理程序,通常借助于存储了必要状态信息的对象来完成此任务。关键字throw抛出异常对象时,会生成一个被抛出对象的副本。在进入异常处理程序之前,进行栈的解退,就会析构该对象副本。同时若try语句块中定义有自动存储类对象或者变量,则在抛出异常后,进行栈的解退时也会同时析构自动类对象。
▶5.7.2.3 捕获具有继承关系的异常类型
由于继承的层次关系,若抛出的异常对象是某个派生类的对象,则该异常对象既可以被该派生类所在catch语句块的处理程序捕获,也可以被该异常对象的基类所在catch语句块捕获。因此,一般把派生类所在的catch语句块放在基类所在的catch语句块前面。(www.xing528.com)
▶5.7.2.4 捕获所有异常
catch语句也可以在圆括号中填以省略号,即catch(...)形式表明可以捕获任何异常类型。
因而若将catch(...)放置在其他catch语句块之前,则其他catch语句块没有机会匹配,也会没有机会被执行,所以总是把catch(...)语句放在catch语句序列的最后。以这种方式捕获异常有两个缺点:无法确定异常的类型;没有命名参数,因而无法在异常处理程序中通过异常对象传入关于异常的信息。[5]
▶5.7.2.5 重新抛出异常
如果catch语句块不处理所捕获的异常,或者即使已经处理过了该异常,都可以用空throw语句重新抛出该异常throw;这个被重新抛出的异常只能由外层的try语句块处理。
▶5.7.2.6 异常规格说明
异常规格说明(exception specifications)使得函数在声明时显式地指出该函数可能抛出的异常类型。在函数声明后面的throw表达式称为异常说明符(exception specifiers)函数异常规格都会被解析,但是不一定会被采纳,只有throw()规格说明会被采纳,这种形式告诉编译器该函数不会抛出任何异常。而throw(...)形式告诉编译器会抛出一个类型不定的异常。
【注释】
[1]王燕,庞淑侠,胡文瑾.面向对象分析设计与编程[M].西安:西安电子科技大学出版社,2018.
[2]毕如田.高等学校应用型本科“十三五”规划教材C++程序设计[M].西安:西安电子科技大学出版社,2016.
[3]曹健.面向对象软件工程实践指南[M].上海:上海交通大学出版社,2017.
[4]王杉.Java面向对象程序设计[M].北京:北京理工大学出版社,2018.
[5]黄宝贵.C++面向对象程序设计[M].北京:清华大学出版社,2020.
免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。