2013-07-31 49 views
3

我正在阅读以下应用C++书籍中的文本。在处理程序函数中抛出异常

可以从我们的处理函数中抛出异常吗?答案是 是的,确实可以抛出错误。问题是这个异常必须在每个异常规范中都可能被 转换,直到捕获异常。如果没有这样做, 应用程序将调用std :: terminate()。对于大型系统,除非您完全理解应用程序的动态,否则此 相当于为每个函数 添加了异常规范。它对你的析构函数中的所有异常都很重要。否则,在这种情况下,std :: terminate()也会被调用。

在上面的文本中,我有以下问题,需要您的理解帮助。

  1. 作者所说的“异常必须在每个可能遍历的期望规范中”是什么意思?

  2. 我的理解是析构函数我们不能使用异常。作者意味着在析构函数中捕获所有异常。

请求以简单例子阐明

感谢您的时间和帮助。

回答

0
  1. 异常规范结果是一个坏主意,我认为它们在该语言的最新版本中被弃用,所以我会忽略它。

  2. 一般来说,析构函数绝不能抛出任何异常。因为它们在抛出/抛出异常时发生的堆栈展开过程中被调用。如果在堆栈退出时引发异常,程序将中止。简单/安全的解决方案是使用try {...} catch (..} {}块来包装析构函数体。

+1

切勿使用或推荐任何人拥有不会重新抛出或中止应用程序的catch-all子句。 – 2013-07-31 13:02:16

+0

@VladLazarenko国际海事组织,这与推荐没有任何关系 - 它是OP询问作者用报价表示的意思,并且“catch all exceptions”在这种情况下非常明确 –

+1

@ mel-:不,捕获所有异常意味着捕获所有例外。好的C++开发人员永远不会使用这样的catch-all子句。只是为了举例,请阅读[this](http://udrepper.livejournal.com/21541.html)。 – 2013-07-31 13:24:11

1

当引发异常并未捕获时,堆栈展开。这意味着将会调用析构函数,一切都会很好地清理。但想一想:

foo::~foo() 
{ 
    bar(); 
} 

如果我们达到,因为未捕获的异常的foo析构函数,并bar();发生抛出,应用程序将立即终止,因为C++不能处理多个异常一次。

这不会发生,如果我们,例如吞咽异常:

foo::~foo() 
{ 
    try { bar(); } catch(...) { /* nom nom */ } 
} 

更新

,第一部分是对异常规格是这样的:

struct foo 
{ 
    void bar() throw(); 
} 

对本规范的有效语法是

throw() // does not throw any exception 
throw(list of exceptions) // may throw one of these exceptions 
throw(...) // may throw any exception 

但正如罗德里格所说,这转过来了这是一个坏主意,因为这些规范导致动态检查(运行时)是否抛出异常,从而显着降低性能。

在C++ 11它替换为noexcept关键字:

noexcept(true) 
noexcept(false) 
noexcept // identical to noexcept(true) 

这是你给的编译器保证,而不是周围的其他方法。

但现在终于到了你的问题。当您在某些嵌套链中给出throw异常规范时,如果在深度嵌套函数中抛出异常,则必须沿途更新每个函数的签名。另一个很好的理由是为什么异常规范是愚蠢的,不应该再使用。

+0

@ nijansen:谢谢澄清。你能否请澄清第一个问题 – venkysmarty

+0

@venkysmarty更新了我的答案 – nijansen

2

通常情况下,异常规范是一个坏主意,因为它在修改规范时会产生大量的重构和缩放问题(这些问题是由autor谈到的)。这是java checked exceptions的情况。 C++没有检查异常,但如果要编写统一的API,异常规范的问题是相同的。

其实exception specifications are deprecated since C++11。 C++ 11使用noexcept说明符来确保函数不引发任何异常。这允许某些编译器优化,并且当然为该函数的用户提供保证。如果一个函数没有noexcept说明符,它可以抛出异常。

例外情况是,正如其名称所示,例外。也就是说,使用try...catch进行流量控制是一种糟糕的编程技术。如果你的程序设计得很好,当抛出异常时,意味着某些事情会非常错误。那是一个特殊的执行情况。通常情况下,例外执行事件转换为执行中止。这就是为什么功能没有try..catch块可以抛出异常的地方。

相关问题