在C++中,您可以通过使用异常说明符指定函数可能会也可能不会抛出异常.例如:
void foo() throw(); // guaranteed not to throw an exception void bar() throw(int); // may throw an exception of type int void baz() throw(...); // may throw an exception of some unspecified type
由于以下因素,我对实际使用它们表示怀疑:
编译器并没有以任何严格的方式真正强制执行异常说明符,因此效益并不高.理想情况下,您希望得到编译错误.
如果函数违反了异常说明符,我认为标准行为是终止程序.
在VS.Net中,它将throw(X)视为throw(...),因此遵守标准并不强.
你认为应该使用异常说明符吗?
请回答"是"或"否"并提供一些理由来证明您的答案.
没有.
以下是几个例子:
使用异常规范无法编写模板代码,
templatevoid f( T k ) { T x( k ); x.x(); }
副本可能会抛出,参数传递可能会抛出,并x()
可能抛出一些未知异常.
异常规范往往会禁止可扩展性.
virtual void open() throw( FileNotFound );
可能演变成
virtual void open() throw( FileNotFound, SocketNotReady, InterprocessObjectNotImplemented, HardwareUnresponsive );
你真的可以这样写
throw( ... )
第一个是不可扩展的,第二个是过于雄心勃勃的,第三个是你在写虚拟函数时的意思.
遗留代码
当你编写依赖于另一个库的代码时,你真的不知道当出现可怕的错误时它会做什么.
int lib_f(); void g() throw( k_too_small_exception ) { int k = lib_f(); if( k < 0 ) throw k_too_small_exception(); }
g
lib_f()
投掷时会终止.这(在大多数情况下)不是你真正想要的.std::terminate()
永远不应该被称呼.最好让应用程序崩溃时出现未处理的异常,从中可以检索堆栈跟踪,而不是静默/暴力死亡.
编写返回常见错误的代码,并在特殊情况下抛出.
Error e = open( "bla.txt" ); if( e == FileNotFound ) MessageUser( "File bla.txt not found" ); if( e == AccessDenied ) MessageUser( "Failed to open bla.txt, because we don't have read rights ..." ); if( e != Success ) MessageUser( "Failed due to some other error, error code = " + itoa( e ) ); try { std::vectork( 1000 ); // ... } catch( const bad_alloc& b ) { MessageUser( "out of memory, exiting process" ); throw; }
然而,当您的库只是抛出自己的异常时,您可以使用异常规范来陈述您的意图.
避免使用C++中的异常规范.你在问题中提出的原因是一个很好的开始.
参见Herb Sutter的"实用的异常规范".
我认为标准除了约定(对于C++)
异常说明符是C++标准中的一个实验,大多数都失败了.
例外情况是no throw说明符很有用,但你也应该在内部添加适当的try catch块以确保代码与说明符匹配.Herb Sutter有一个关于这个主题的页面.Gotch 82
另外我认为值得描述异常保证.
这些基本上是关于如何通过转义该对象上的方法的异常影响对象状态的文档.不幸的是,它们没有被编译器强制执行或以其他方式提及.
提升和例外
异常转义方法后,无法保证对象的状态
在这些情况下,不应再使用该对象.
在几乎所有情况下,这应该是方法提供的最小保证.
这可以保证对象的状态定义良好,并且仍然可以一致地使用.
这可以保证方法成功完成
或抛出异常并且对象状态不会改变.
该方法保证不允许任何异常传播出该方法.
所有析构函数都应该做出这种保证.
| NB如果一个异常逃离析构函数时异常已经传播
| 申请将终止
当您违反异常规范时,gcc将发出警告.我所做的是使用宏只在"lint"模式下使用异常规范明确编译以检查以确保异常与我的文档一致.
唯一有用的异常说明符是"throw()",如"不抛出".