似乎普遍认为异常规范并没有像人们想象的那么多。但我想知道只使用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 );
答案 0 :(得分:8)
是的但是当你抛出一些不是从std :: exception派生的东西时,你会发生什么?
您希望申请终止吗? 没有堆栈展开而不是调用析构函数来整理代码,只是退出应用程序。
Java和C ++异常规范之间的区别在于Java在编译时检查规范。另一方面,C ++在运行时进行所有检查。所以当你的规格被违反时,已经太晚了。
即使在Java代码中也存在停止使用它们的动作。在项目开始时,往往会发生的事情是严格定义异常规范。但随着代码的增长和变得越来越复杂,规范被稀释为越来越普遍的形式。这是因为随着代码的增长,可以抛出更多异常,如果无法立即处理它们,则需要将整个调用链的异常规范修改回可以处理它们的位置。 (注意我不是Java专家,但我确实在一个成熟的Java代码库中玩。)
值得一提的唯一异常规范(我认为)是no throw规范。这确实有一个有效的应用程序(但你必须在try / catch(...)块中使用它。)
另请阅读Herb Sutters article:
答案 1 :(得分:4)
异常规范基本上没用。 Martin York已经与Herb Sutter关于他们的帖子有关,但总之,你遇到了以下问题:
所以你所做的就是让你更难捕捉到可能抛出的异常,同时减慢程序的速度。真的没什么意义。
答案 2 :(得分:2)
在符合标准的编译器上,添加非空异常规范会在函数周围生成等效的try / catch块。虽然可以以没有运行时开销的方式实现这一点,但在某些当前的编译器上,您确实会遇到开销。
因此可能会产生费用,而且如果someFunction
或其调用的内容引发非std::exception
派生的异常,则会调用std::unexpected
,而不是未处理的异常机制。
所以我想我的回答是'不': - )
答案 3 :(得分:1)
我会这样做:
void someFunction() /* throw (std::exception) */;
throw语句在函数声明中的唯一作用是修改它的签名:指向“void x()”的指针和指向“void x()throw y”的指针是两种不同的类型。
通过这种方式,您仍然可以记录函数可能会抛出某些内容,并且您没有丢失任何内容,因为无论如何c ++编译器都不会强制执行任何约束。