10

我刚刚读到在 C++11 标准修订版中,不推荐使用异常规范。我以前认为指定你的函数可能会抛出什么是好的做法,但显然不是这样。

在阅读了 Herb Stutter 被广泛引用的文章之后,我不禁想知道:到底为什么异常规范是以它们的方式实现的,为什么委员会决定弃用它们而不是在编译时检查它们?为什么编译器甚至允许抛出未出现在函数定义中的异常?对我来说,这听起来像是在说“你可能不应该指定你的函数返回类型,因为当你指定int f(),但return 3.5;在它里面,你的程序可能会崩溃。” (即,与强类型的概念区别在哪里?)

(由于 s 中缺乏异常规范支持typedef,鉴于模板语法可能是图灵完备的,实现这听起来很容易。)

4

2 回答 2

11

最初的原因是,鉴于现有代码的主体,不可能可靠地检查,而且没有说明符意味着任何东西都可以抛出。这意味着如果静态检查生效,以下代码将无法编译:

double
safeSquareRoot( double d ) throw()
{
    return d > 0.0 ? sqrt( d ) : 0.0;
}

此外,异常的目的是远距离报告错误,这意味着中间函数不应该知道它们调用的函数可能会抛出什么。对它们要求异常说明符会破坏封装。

函数需要了解可能发生的异常的唯一真实情况是知道哪些异常不会发生。特别是,除非可以保证某些函数永远不会抛出异常,否则不可能编写线程安全的代码。即使在这里,由于上述原因,静态检查也是不可接受的,因此异常规范的设计更像是一个您无法停用的断言:当您编写 时throw(),如果函数被异常终止。

Java 中的情况有些不同。在 Java 中,没有真正的输出参数,这意味着如果函数也有返回值,则不能使用返回码。结果是,在返回代码更可取的许多情况下使用异常。而这些,你必须知道,并立即处理。对于真正应该是例外的事情,Java 有java.lang.RuntimeException (不管是静态的还是其他方式都没有检查)。而且它没有办法说一个函数永远不能抛出异常。Error在中止程序更合适的情况下,它还使用未经检查的异常(称为)。

于 2013-08-27T17:41:07.893 回答
-1

如果函数f() throw(int)调用函数g() throw(int, double)会发生什么?

编译时检查将阻止您的函数调用具有不太严格的抛出说明符的任何其他函数,这将是一个巨大的痛苦。

于 2013-08-27T17:18:48.903 回答