std::set_unexpected
指定一个处理方法, 在函数抛出与异常声明不相符的异常时调用. 比如下面这样#include <stdexcept>
#include <iostream>
void func_throws() throw (std::out_of_range)
{
throw std::logic_error("danger!");
}
void throw_another()
{
throw std::out_of_range("safe");
}
int main()
{
std::set_unexpected(throw_another);
try {
func_throws();
} catch (std::out_of_range e) {
std::cerr << e.what() << std::endl;
}
return 0;
}
不过换个写法, 如果处理函数里面也继续抛
std::logic_error
#include <stdexcept>
#include <iostream>
void func_throws() throw (std::out_of_range)
{
throw std::logic_error("danger!");
}
void throw_another()
{
throw std::logic_error("not safe!");
}
int main()
{
std::set_unexpected(throw_another);
try {
func_throws();
} catch (std::out_of_range e) {
std::cerr << e.what() << std::endl;
}
return 0;
}
也就是说, 处理函数相当于替换原来的函数, 在错误处原地重新抛出一个异常, 但异常必须匹配原来函数的异常声明, 否则异常仍然无法捕捉. 明显扯淡么, 随便找两个异常声明不搭界的函数, 这货不就不管用了么, 总不能随抛随设吧.
当然, 标准还规定了一个很犀利的异常类型, 叫做
std::bad_exception
, 如果把这家伙加进异常声明, 那就给力了#include <stdexcept>
#include <iostream>
void func_throws() throw (std::out_of_range, std::bad_exception)
{
throw std::logic_error("danger!");
}
void throw_another()
{
throw;
}
int main()
{
std::set_unexpected(throw_another);
try {
func_throws();
} catch (std::bad_exception e) {
std::cerr << e.what() << std::endl;
}
return 0;
}
throw_another
里面摇身一变, 成了 std::bad_exception
, 不过看 std::cerr
吐出来的东西, 信息都消失了啊, 这不是坑爹么.其实说到底, 这跟写成
void throw_another()
{
throw std::bad_exception("std::bad_exception");
}
而且, 要达到这个效果, 需要在每个觉得可能出岔子的函数的异常列表里面加上
std::bad_exception
, 编译器难道你没有能力帮着合成一个进去么? 这简单能力有没有?! 有没有?!所以, 删掉吧, 异常声明! <- 結論