抛出意外异常时,为什么此程序不会中止?

InQ*_*ive 7 c++ exception abort

我正在经历C++ FAQ 2nd Edition, FAQ 9.04- What is an exception specification?.

在那里,提到如果我们从其签名指定一组预定义异常类型的函数抛出一个意外异常,它应该调用unexpected()->terminate()->abort().但是我的程序捕获了意外的异常而不是abort()它,为什么?

#include<iostream>
using namespace std;

class Type1{};
class Type2{};
class Type3{};

void func() throw(Type1, Type2)
{
    throw Type3();
}

int main()
{
    try{
        func();
    }
    catch (Type1 &obj1)
    {
        cout << "Type1 is caught" << endl;
    }
    catch (Type2 &obj2)
    {
        cout << "Type2 is caught" << endl;
    }
    catch (Type3 &obj3)
    {
        cout << "Type3 is caught" << endl;
    }
}
Run Code Online (Sandbox Code Playgroud)

在这里,我得到的输出Type3 is caught不应该发生.

IDE:VS2013

Ser*_*sta 6

正如Adriano Repetti所说,MSVC会忽略异常规范.但是有一些原因.

等岗位从SO解释说,异常规范解释,编译器不能强制例外控制,编译时,必须生成代码在运行时只是控制它.这就是为什么编译器(特别是MSVC)的支持很差.

它引用了GOTW的一篇非常详细的文章,结论是:

所以这就是我们社区今天所学到的最佳建议:

  • 道德#1:永远不要写异常规范.
  • 道德#2:除了可能是空的,但如果我是你,我甚至会避免.


Adr*_*tti 4

来自 MSDN:

除 throw() 之外的函数异常说明符会被解析但不会被使用。这不符合 ISO C++ 规范第 15.4 节

Visual C++ 根本不遵循标准(引用Mohit 答案中的标准)。

编辑:关于子问题“为什么不?” 我尝试从评论中总结已经说过的话。

  • 首先,商业编译器总是要面对成本/效益比。如果实现一项功能的成本(直接或间接)超过其价值(直接或间接),那么它很可能不会被实现(至少不会很快)。在我看来,这是一个重要的考虑因素,一个小功能可能会影响编译器的复杂性和性能(另请阅读Eric Lippert的有关此主题的许多 C# 帖子之一)。
  • 实现一个功能可能会极大地影响性能(这似乎是本例中的原因,请参阅Serge 的回答)。
  • 一些规范不清楚和/或有缺陷。另请参阅嵌套类的意义是什么?
  • 更改某些内容可能会破坏现有代码。始终认真考虑这些重大更改(特别是如果它们在编译时但在运行时不会破坏任何内容)。这什么时候可能发生?例如:
    • 编译器引入了语言扩展,后来在未来的标准中断言了一些不同的东西。
    • 规格不清楚,或者他们留下了具体实施的细节。
    • 规范实现中的编译器错误是众所周知的。例如,当 Microsoft 重写 C# 编译器时,Roslyin 实现必须在旧编译器中重现错误。另请参阅SLAks 的有关重大更改的博客(他们并未对所有内容都这样做)。
  • 某些功能(例如本例中的功能)对您的代码几乎没有增加任何价值,并且在商业实现之前(例如,不要忘记 MSVC++ 的更新频率低于 GCC),它们已被弃用,因此无需支持他们。

  • @InQusitive:你正在学习错误的语言。C++03 已经死了,你应该学习 C++14(或至少 C++11)。自例外规范以来,该标准已进行了两次重大更新。它被删除的原因是因为它基本上没有用(除了被明确替换为“noexcept”的非抛出规范) (2认同)