在异常规范中仅使用std :: exception

时间:2008-12-04 17:10:07

标签: c++ exception

似乎普遍认为异常规范并没有像人们想象的那么多。但我想知道只使用std :: exception的规范是否是一个很好的折衷方案:

void someFunction()
    throw ( std::exception );
  • 它记录了此方法/函数可能抛出异常的事实。

  • 它将确保只抛出从std :: exception派生的异常,而不是某些奇特的类,如std :: string或int。

那么,这会比没有任何规范更好吗?

更新

关于运行时 - 开销:将其视为断言的用法。无论运行时开销如何,您都在使用断言,对吧?我知道你通常可以为发布版本禁用它们,所以可能更好的方法是将异常规范包装在一个宏中,这样你就可以为发布版本禁用它。类似的东西:

#ifdef DEBUG
    #define THROW( exception ) throw ( exception )
#else
    #define THROW( exception )
#endif

void someFunction()
    THROW( std::exception );

4 个答案:

答案 0 :(得分:8)

是的但是当你抛出一些不是从std :: exception派生的东西时,你会发生什么?

您希望申请终止吗? 没有堆栈展开而不是调用析构函数来整理代码,只是退出应用程序。

Java和C ++异常规范之间的区别在于Java在编译时检查规范。另一方面,C ++在运行时进行所有检查。所以当你的规格被违反时,已经太晚了。

即使在Java代码中也存在停止使用它们的动作。在项目开始时,往往会发生的事情是严格定义异常规范。但随着代码的增长和变得越来越复杂,规范被稀释为越来越普遍的形式。这是因为随着代码的增长,可以抛出更多异常,如果无法立即处理它们,则需要将整个调用链的异常规范修改回可以处理它们的位置。 (注意我不是Java专家,但我确实在一个成熟的Java代码库中玩。)

值得一提的唯一异常规范(我认为)是no throw规范。这确实有一个有效的应用程序(但你必须在try / catch(...)块中使用它。)

另请阅读Herb Sutters article

这个帖子在SO:Should I use an exception specifier in C++?

答案 1 :(得分:4)

异常规范基本上没用。 Martin York已经与Herb Sutter关于他们的帖子有关,但总之,你遇到了以下问题:

  1. 他们被MSVC忽略了,
  2. 他们的影响与此类似 Java的。检查规格 在运行时,导致性能 打了,没有给你 你进入的编译时验证 Java的。所有你说的是“插入额外的代码,这样当一个 抛出异常,检查其类型,然后 要么正常扔,要么打电话 意外()代替。
  3. 所以你所做的就是让你更难捕捉到可能抛出的异常,同时减慢程序的速度。真的没什么意义。

答案 2 :(得分:2)

在符合标准的编译器上,添加非空异常规范会在函数周围生成等效的try / catch块。虽然可以以没有运行时开销的方式实现这一点,但在某些当前的编译器上,您确实会遇到开销。

因此可能会产生费用,而且如果someFunction或其调用的内容引发非std::exception派生的异常,则会调用std::unexpected,而不是未处理的异常机制。

所以我想我的回答是'不': - )

答案 3 :(得分:1)

我会这样做:

void someFunction() /* throw (std::exception) */;

throw语句在函数声明中的唯一作用是修改它的签名:指向“void x()”的指针和指向“void x()throw y”的指针是两种不同的类型。
通过这种方式,您仍然可以记录函数可能会抛出某些内容,并且您没有丢失任何内容,因为无论如何c ++编译器都不会强制执行任何约束。