C++解析-外传篇(2):函数的异常规格说明

时间:2023-03-09 18:31:02
C++解析-外传篇(2):函数的异常规格说明

0.目录

1.异常规格说明

2.unexpected() 函数

3.小结

1.异常规格说明

问题:

如何判断一个函数是否会抛出异常,以及抛出哪些异常?

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

C++解析-外传篇(2):函数的异常规格说明

异常规格说明的意义:

  • 提示函数调用者必须做好异常处理的准备
  • 提示函数的维护者不要抛出其它异常
  • 异常规格说明是函数接口的一部分

问题:

如果抛出的异常不在声明列表中,会发生什么?

下面的代码的输出什么?

C++解析-外传篇(2):函数的异常规格说明

示例——异常规格之外的异常:

#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() 函数

  • 函数抛出的异常不在规格说明中,全局 unexpected() 被调用
  • 默认的 unexpected() 函数会调用全局的 terminate() 函数
  • 可以自定义函数替换默认的 unexpected() 函数实现
  • 注意:不是所有的C++编译器都支持这个标准行为

unexpected() 函数的替换:

  • 自定义一个无返回值无参数的函数
    1. 能够再次抛出异常
      1. 当异常符合触发函数的异常规格说明时,恢复程序执行
      2. 否则,调用全局 terminate() 函数结束程序
  • 调用 set_unexpected () 设置自定义的异常函数
    1. 参数类型为 void (*) ()
    2. 返回值为默认的 unexpected() 函数入口地址

示例1——自定义 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()

exit();改为throw 1;后的运行结果:

示例2——自定义 unexpected() 函数:

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() 中能够再次抛出异常
    1. 异常能够匹配,恢复程序的执行
    2. 否则,调用 terminate() 结束程序