异常被引发之后,通常在两种情况下会导致问题:①若异常是在包含异常规范的函数中引发的,则必须与规范列表中的某种异常匹配,否则称为意外异常。在默认情况下,这将导致程序异常终止。②若异常不在函数中引发的,则该异常必须被捕获。若没有被捕获,则异常被称为未捕获异常。默认情况下,这会导致程序异常终止。对于意外异常和未捕获异常的反应,程序员可以根据情况自行设定。
1.未捕获异常
未捕获异常不会导致程序立刻异常终止。相反,可以通过调用terminate()函数终止程序。默认情况下,terminate()会调用abort()函数。因此,程序员可以通过指定terminate()应调用的函数来实现修改terminate()的行为。下面介绍set_terminate()和terminate()函数的使用方法。这两个函数通常在头文件<exception>中声明。
其中,typedef使terminate_handler成为一种类型的名称——指向没有参数和返回值的函数指针。set_terminate()函数的参数必须是不带任何参数且返回类型为void的函数名称或函数地址。执行时,其返回值为参数的地址。若调用set_terminate()函数很多次,则terminate()将调用最后一次set_terminate()设置的函数。
假定希望未捕获的异常会使程序打印一条消息,之后调用exit()函数,将退出状态值设置为5。在使用时,必须包含头文件<exception>。
设计一个上述功能的myQuit()函数。
在main()函数的起始部分,设置set_terminate(myQuit)。一旦程序中某些异常被触发,并没有被捕获,程序会调用terminate(),而该函数会触发调用myQuit()函数。
例8-3
程序执行结果:
2.unexpected()异常处理
程序员应该明确哪些异常是必须要捕获的。因为在默认情况下,未捕获的异常将导致程序异常终止。通常,从原则上讲,异常规范需要包含函数调用的各种可能引发的异常。例如,若A()函数调用B()函数,而函数B会触发某个对象异常,则异常规范中应包含该对象。
如果程序引发了异常规范中没有的异常(即意外异常),此行为与未捕获的异常极其相似。如果发生意外异常,程序会调用unexpected()函数。unexpected()函数会调用terminate()函数,而terminate()函数默认情况下会调用abort()函数。和set_terminate()相对应,STL提供了set_unexpected()函数用于修改unexpected()函数的行为。unexpected()函数和set_un-expected()一样,也是包含在头文件<exception>中的。
和set_terminate()函数不同,set_unexpected()函数的参数是严格受限制的。通常,un-expected_handler函数可以有以下行为:
1)调用terminate()、abort()或exit(),从而终止程序。(www.xing528.com)
2)触发异常。
就第二种行为而言,引发异常的结果取决于unexpected_handler所引发的异常及引发异常函数的异常规范。一般包括以下几种情况:
①若新引发的异常与原来的异常规范匹配,则程序会开始进行正常处理,即寻找与新引发的异常匹配的catch块。基本上,此方法将用于预期的异常取代意外异常。
②若新引发的异常与原有的异常规范不匹配,且异常规范中不包括std::bad_exception类型,则程序还是会调用terminate()函数。类bad_exception是从exception派生而来的,其类的声明在头文件<exception>中。
③新引发的异常与原有异常规范不匹配,原来的异常规范中包含std::bad_exceptipon类型,不匹配的异常会被std::bad_exception异常取代。
简而言之,程序设计的目的是要捕获所有异常。通常可以采取如下处理方法:
1)必须包含头文件<exception>。
2)设计一个替代函数,将意外异常转换为bad_exception异常。该函数的原型如下:
使用throw时,若不指定异常,将导致重新引发的(意外)异常。若异常规范中包含此类型,该异常将被bad_exception对象所取代。
在main()函数的开始位置,将“意外异常”诱发的操作设定为调用自定义的myunex-pected()。最后,将bad_exception类型包括在异常规范中,并添加以下catch块:
例8-4
例8-4的执行结果为:
免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。