乐趣区

【C++】 外传篇 2_函数的异常规格说明

函数的异常规格说明
问题:如何判断一个函数是否会抛出异常,以及抛出哪些异常?

C++ 提供语法用于声明函数所抛出的异常
异常声明作为函数声明的修饰符,写在参数列表后面

/** 可能抛出任何异常 */
void func1();

/** 只能抛出的异常类型:char 和 int */
void func2() throw(char, int);

/** 不抛出任何异常 */
void func3() throw();

异常规格说明的意义

提示函数调用者必须做好异常处理的准备

提示函数维护者不要抛出其它异常

异常规格说明是函数接口的一部分

问题:如果抛出的异常不在声明列表中,会发生什么?
编程实验:异常规格之外的异常
#include <iostream>

using namespace std;

void func() throw(int)
{
cout << “func()” << endl;

throw ‘c’;
}

int main()
{
try
{
func();
}
catch(int)
{
cout << “catch(int)” << endl;
}
catch(char)
{
cout << “catch(char)” << endl;
}

return 0;
}
输出:[g++]
func()
terminate called after throwing an instance of ‘char’
已放弃

输出:[vc2010]
func()
catch(char)

注意:
g++:编译后可执行程序异常停止
vc2010:func(); 抛出的异常被被捕获

函数抛出的异常不在规格说明中,全局 unexpected() 被调用
默认的 unexpected() 函数会调用全局的 terminated() 函数
可以自定义函数替换默认的 unexpected() 函数实现

注意:不是所有的 C++ 编译器都支持这个标准行为 (例:vc2010)

unexpected() 函数的替换

自定义一个无参数无返回值的函数

能够再次抛出异常

当异常符合触发函数的异常规格说明时,恢复程序执行
否则,调用全局 terminate() 函数结束程序

调用 set_unexpected() 设置自定义的异常函数

参数类型为 void(*)()
返回值为默认的 unexpected() 函数入口地址

编程实验:自定义 unexpected() 函数
#include <iostream>

using namespace std;

void my_unexpected()
{
cout << “void my_unexpected()” << endl;

// exit(1);

throw 1;
}

void func() throw(int)
{
cout << “func()” << endl;

throw ‘c’;
}

int main()
{
set_unexpected(my_unexpected);

try
{
func();
}
catch(int)
{
cout << “catch(int)” << endl;
}
catch(char)
{
cout << “catch(char)” << endl;
}

return 0;
}
输出:[g++]
func()
void my_unexpected()
catch(int)

输出:[vc2010]
func()
catch(char)

总结:对于异常规格说明,不同的编译器有不同的行为。在实际项目中,可编写测试程序查看使用的编译器有没有遵循 C++ 规范。
小结

C++ 中的函数可以声明异常规格说明
异常规格说明可以看作接口的一部分
函数抛出的异常不在规格说明中,unexpected() 被调用

unexpected() 中能够再次抛出异常

异常能够匹配,恢复程序的执行
否则,调用 terminate() 程序结束

以上内容参考狄泰软件学院系列课程,请大家保护原创!

退出移动版