我应该在C ++中使用异常说明符吗?

在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(...),因此对标准的遵循性不强。

您认为应该使用异常说明符吗?

请回答“是”或“否”,并提供一些理由来证明您的回答合理。


慕婉清6462132
浏览 404回答 3
3回答

慕的地8271018

没有。这里有几个例子说明为什么:模板代码无法使用异常规范编写,template<class T>void f( T k ){&nbsp; &nbsp; &nbsp;T x( k );&nbsp; &nbsp; &nbsp;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 ){&nbsp;&nbsp; &nbsp;int k = lib_f();&nbsp; &nbsp;if( k < 0 ) throw k_too_small_exception();}glib_f()抛出时将终止。(在大多数情况下)这不是您真正想要的。std::terminate()永远不应该被调用。总是让应用程序因未处理的异常而崩溃(从中可以检索堆栈跟踪)总是比静默/剧烈地消亡更好。编写返回常见错误并在特殊情况下抛出的代码。Error e = open( "bla.txt" );if( e == FileNotFound )&nbsp; &nbsp; MessageUser( "File bla.txt not found" );if( e == AccessDenied )&nbsp; &nbsp; MessageUser( "Failed to open bla.txt, because we don't have read rights ..." );if( e != Success )&nbsp; &nbsp; MessageUser( "Failed due to some other error, error code = " + itoa( e ) );try{&nbsp; &nbsp;std::vector<TObj> k( 1000 );&nbsp; &nbsp;// ...}catch( const bad_alloc& b ){&nbsp;&nbsp; &nbsp;MessageUser( "out of memory, exiting process" );&nbsp; &nbsp;throw;}但是,当您的库仅引发您自己的异常时,您可以使用异常规范说明您的意图。

烙印99

我认为除约定外(对于C ++),标准例外说明符是在C ++标准中进行的一项实验,多数失败。唯一的例外是,不抛出说明符很有用,但您还应该在内部添加适当的try catch块,以确保代码与说明符匹配。Herb Sutter在此页面上有一个页面。戈特82另外,我认为值得描述例外保证。这些基本上是有关对象的状态如何受到异常转义的方法的文档。不幸的是,它们没有被编译器强制执行或以其他方式提及。提升和例外例外保证不保证:在异常转义方法之后,无法保证对象的状态。在这些情况下,不应再使用该对象。基本保证:在几乎所有情况下,这都应该是方法提供的最低保证。这保证了对象的状态定义正确,并且仍然可以被一致地使用。强有力的保证:(又名交易保证)这保证了该方法将成功完成,否则将引发异常并且对象状态不会更改。无投掷保证:该方法保证不允许异常传播到该方法之外。所有破坏者都应作出此保证。| 注意:如果在已传播异常的情况下异常逃逸了析构函数| 该应用程序将终止

波斯汪

异常规范不是C ++中非常有用的工具。但是,如果与std :: unexpected结合使用,则/ is /有很好的用途。在某些项目中,我要做的是编写具有异常规范的代码,然后使用将抛出我自己设计的特殊异常的函数调用set_unexpected()。构造后,此异常获取回溯(以特定于平台的方式),并从std :: bad_exception派生(如果需要,可以传播该异常)。如果它像往常一样引起了一个terate()调用,则回溯将由what()打印(以及引起它的原始异常;不难发现),因此我获得了合同所在位置的信息。违反,例如引发了意外的库异常。如果这样做,我将永远不允许传播库异常(std异常除外),并从std :: exception派生我的所有异常。如果库决定抛出,我将捕获并转换为自己的层次结构,从而使我能够始终控制代码。由于明显的原因,调用依赖函数的模板化函数应避免使用异常规范。但是无论如何,很少有带有库代码的模板化函数接口(很少有库确实以有用的方式使用模板)。
打开App,查看更多内容
随时随地看视频慕课网APP