C++异常处理程序中嵌套的try...catch有什么作用?

24

我想在我的异常处理程序中执行的代码本身可能会抛出异常。

以下结构在C++中是否合法?如果是,有没有什么缺陷?

try
{
    // ...
}
catch (const E&)
{
    try
    {
        // ...
    }
    catch (const F&)
    {

    }
}
2个回答

30

实际上,甚至有一种有趣的技巧可以使用嵌套的try/catch块:假设您有多个需要有效处理相同异常的函数。特别是在包装另一个接口时,这是常见的情况。在这种情况下,可以捕获所有异常,从异常处理程序调用一个函数,并在该函数中重新引发异常以实现实际的异常处理:

void fancy_handler() {
    try {
        throw; // assumes that fancy_handler() is called from catch-clause
    } catch (std::runtime_error const& rt) {
        std::cout << "runtime-error: " << ex.what() << "\n";
    } catch (std::exception const& ex) {
        std::cout << "excption: " << ex.what() << "\n";
    } catch (...) {
        std::cout << "unknown exception\n";
    }
}

void foo() { try { do_foo(); } catch (...) { fancy_handler(); } }
void bar() { try { do_bar(); } catch (...) { fancy_handler(); } }

我只是喜欢避免重复的[非平凡]代码!


1
等等,你真的可以从嵌套函数中throw吗?我从未见过这样的事情! - Mooing Duck
2
@MooingDuck:只要你从catch块中调用了函数,就可以重新抛出异常。更有趣的是,这在Java和C#中也适用(我最初在Java中使用这种技术来处理大量不同的数据库异常;尽管我是C++专家而不是Java专家;) - Dietmar Kühl
我得查阅标准并学习细节和角落。 - Mooing Duck
1
@MooingDuck:我只能告诉你C++方面的内容:除了第7段中的except.handle:“当catch子句的形式参数(如果有)的初始化完成时,处理程序被视为处于活动状态。”和第8段中的except.throw:“没有操作数的throw表达式重新抛出当前处理的异常[...]”。 - Dietmar Kühl
我特别查找的部分是 int main() {fancy_handler();} - Mooing Duck
@MooingDuck:好的,由于这是一次没有活动异常的重新抛出,因此它调用了std::terminate()(请参见except.throw第9段:“如果当前没有处理异常,则执行没有操作数的throw表达式调用std: terminate()。”)。...或者换句话说,fancy_handler()有一个前提条件,尽管是奇怪的:它只能从catch块中调用。 - Dietmar Kühl

27

不,没有任何不利因素。这是你应该采取的方式。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接