1.异常规格说明
(1)问题:如何判断一个函数是否会抛出异常,以及抛出哪些异常?
(2)异常规格说明
-
C++提供语法用于声明函数所抛出的异常
-
异常声明作为函数声明的修饰符,写在参数列表后面
(3)异常规格说明的意义:
-
提示函数的调用者必须做好异常处理的准备
-
提示函数的维护者不要抛出其它异常
-
异常规格说明是函数接口的一部分
(4)问题:如果抛出的异常不在声明列表中,会发生什么?
下面的代码的输出什么?
编程实验:异常规格之外的异常
#include <iostream>
using namespace std;
void func() throw(int)
{
cout << "func()";
cout << endl;
throw 'c';
}
int main()
{
try
{
func();
}
catch(int)
{
cout << "catch(int)";
cout << endl;
}
catch(char)
{
cout << "catch(char)";
cout << endl;
}
return 0;
}
运行结果:不同编译器运行结果不一样
[root@bogon Desktop]# g++ test.cpp
[root@bogon Desktop]# ./a.out
func()
terminate called after throwing an instance of 'char'
Aborted (core dumped)
2.unexpected() 函数
(1)unexpected() 函数
-
函数抛出的异常不在规格说明中,全局 unexpected() 被调用
-
默认的 unexpected() 函数会调用全局的 terminate() 函数
-
可以自定义函数替换默认的 unexpected() 函数实现
-
注意:不是所有的C++编译器都支持这个标准行为
(2)unexpected() 函数的替换
-
自定义一个无返回值无参数的函数
- 能够再次抛出异常
-
当异常符合触发函数的异常规格说明时,恢复程序执行
-
否则,调用全局 terminate() 函数结束程序
-
- 能够再次抛出异常
-
调用 set_unexpected () 设置自定义的异常函数
-
参数类型为
void (*) ()
-
返回值为默认的 unexpected() 函数入口地址
-
编程实验:自定义 unexpected() 函数
#include <iostream>
#include <cstdlib>
#include <exception>
using namespace std;
void my_unexpected()
{
cout << "void my_unexpected()" << endl;
exit(1);
}
void func() throw(int)
{
cout << "func()";
cout << endl;
throw 'c';
}
int main()
{
set_unexpected(my_unexpected);
try
{
func();
}
catch(int)
{
cout << "catch(int)";
cout << endl;
}
catch(char)
{
cout << "catch(char)";
cout << endl;
}
return 0;
}
运行结果:
[root@bogon Desktop]# g++ test.cpp
[root@bogon Desktop]# ./a.out
func()
void my_unexpected()
编程实验2: 自定义 unexpected() 函数
将exit();
改为throw 1;
后的运行结果
void my_unexpected()
{
cout << "void my_unexpected()" << endl;
// exit(1);
throw 1;
}
运行结果:
[root@bogon Desktop]# g++ test.cpp
[root@bogon Desktop]# ./a.out
func()
void my_unexpected()
catch(int)
(程序恢复执行了)
(unexpected() 函数是正确处理异常的最后机会,如果没有抓住这次机会,全局的 terminate() 函数就会被调用,当前程序就只能以异常结束告终。)
3.小结
-
C++中的函数可以声明异常规格说明
-
异常规格说明可以看作接口的一部分
-
函数抛出的异常不在规格说明中,unexpected() 被调用
-
unexpected() 中能够再次抛出异常
-
异常能够匹配,恢复程序的执行
-
否则,调用 terminate() 结束程序
-