繁体   English   中英

为什么bad_exception不会自动抛出?

[英]Why bad_exception is not thrown automatically?

为什么这段代码没有错误运行? 遇到意外异常时,难道不应该自动调用bad_exception吗? 还是有必要为其设置处理程序?

#include <iostream>
#include <exception>
using namespace std;
class C{};
void test() throw(bad_exception)
{
    throw C();
}
int main()
{
    try
    {
         test();
    } catch(bad_exception& e)
    {
        cout << "Caught ";
    }
}

在C ++ 03理论中:如果引发的异常不在异常规范中,则将调用unexpected() 如果您尚未通过set_unexpected()设置意外的处理程序, set_unexpected()这意味着您将观察到terminate()被调用的情况。 如果设置一个意想不到的处理程序不调用终止,但抛出一个异常,如果该异常不能在你的异常规范中列出,它被翻译成bad_exception。 因此,为了获得预期的结果,请首先使用适当的处理程序调用set_unexpected()

在C ++ 03的实践中:有些编译器根本不支持异常规范( throw()除外),其他编译器只是不评估/检查其正确性。 正如Herb Sutter指出的那样 ,异常规范创建了一个笨拙的“影子类型系统”,该系统很难正确处理(如果可能的话)。 因此..

...在C ++ 11中: 不赞成使用 Exception规范。 您宁可不要使用它们。 但是,有一个nothrow运算符的功能与throw()略有不同


PS:那么为什么C ++ 03中有std :: bad_exception? 您拥有三个不同的代码区域:

  • 您正在为其编写异常规范的函数。
  • 您从该函数调用的“外部”代码可能会或可能不会引发与您的规范不匹配的异常。
  • (可能也是未知的)意外的处理程序可以是任何东西,应该终止/退出/中止程序或抛出任何东西。

因此,如果“外来”代码引发了违反您的异常规范的异常,则可能会产生以下三种结果:

  1. 处理程序终止程序。 除非您在函数中设置自己的处理程序,否则您将无能为力。
  2. 处理程序将引发与您的异常规范匹配的异常。 一切都很好。
  3. 处理程序会抛出其他内容。 您希望运行时现在做什么? 这就是bad_exception出现的地方:如果在您的规范中,则“其他”将转换为bad_exception,然后程序继续。 如果不是,则终止被调用。

在函数内设置自己的处理程序将禁用任何其他仅想使用您的函数的人先前设置的处理程序。 他不会期望您禁用他的处理程序。 此外,该处理程序是一种全局的“假设-如果”策略,因此您在单个函数实现中就不必担心。

这应该调用std::unexpected ,默认情况下调用std::terminate()因为抛出的异常不是异常规范的一部分。

(此处适用于Linux上的g ++,Solaris上的 Sun Oracle CC,AIX BTW上的IBM xlC)

如果您安装了意外的处理程序,它将按您期望的那样工作:

include <iostream>
#include <exception>
using namespace std;
class C{};

void myunexpected()
{
    throw std::bad_exception();
}

void test() throw(std::bad_exception)
{
    throw C();
}
int main()
{
    try
    {
        set_unexpected(myunexpected);
        test();
    } catch(std::bad_exception& e)
    {
        std::cout << "Caught ";
    }
}

按照[except.unexpected],当一个函数抛出其动态异常规范中未列出的异常时,将调用std::unexpected() 根据[unexpected.handler], std::unexpected()的默认实现只是调用std::terminate()

但是,程序可以安装自己的处理程序,该处理程序可以(重新)引发异常。 如果由此引发的异常不会被动态异常规范允许,它可以被替换std::bad_exception 允许的时候。

您的catch块将仅捕获bad_exception类型或其子类型的异常。 C不符合此条件。

实际上, 这个问题与您的问题非常相似。 可接受的答案说明,如果您的函数抛出与规范不匹配的异常(如果存在),则将调用std::unexpected ,默认情况下将调用std::terminate

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM