catch (...)
是一个所谓的“catch all”块。它会捕获任何 C++异常。
catch(std::exception& e)
将捕获只有从std::exception
派生的例外。
这里是一个将被捕获所有被称为一个例外的例子,但不是第二个版本:
throw 42;
这听起来很奇怪,你,它是。要认识到的重要一点是,任何东西都可以作为C++异常抛出 - 不仅仅是exception
或从exception
派生的东西。正如@ bames53在注释中提到的那样,没有任何异常类型来源于所有异常,就像其他语言一样。
重要的是要注意,一个全通块很容易被滥用。事实上,作为一般的经验法则,最好假设所有全部封锁都是程序缺陷。当然,编程中并没有“永远”,但是当你学习使用异常时,这是一个安全的假设。
为什么catch-all模块是邪恶的原因是因为它们通常如何使用。通常情况下,一个天真的程序员会编写一个捕获所有程序来试图捕捉任何编程错误,然后批判地继续让程序运行,就好像什么也没发生一样。这是一场等待发生的灾难。程序状态现在是不确定的。某个地方出了问题。你不能安全地忽略异常,并继续像一切都很好。即使你的程序继续运行,可能会在某处发生微妙的堆损坏,会掺杂程序的计算或其输出。发生堆损坏时,作为程序员可以希望的最好的事情是立即崩溃。这样你就可以在腐败点得到一个调用堆栈和一个转储文件,并找到并解决问题。但是,当你有一个全面的地方,你已经失去了腐败发生的所有背景。在你的代码中找到真正的缺陷几乎是不可能的。
当然,捕获所有处理程序是有效的和有价值的用法。最常见的一种情况是编写一个全局异常处理程序,然后重新编号为throw
。这个全局处理程序可以启动某种故障记录,可能是通过记录错误本身,或者产生一个外部程序来记录失败程序以外的记录。通过重新抛出异常,您可以为委托人提供处理可以处理的异常的机会,同时允许无法处理的异常终止程序。
重新执行异常很简单。只需拨打throw
不带参数,如:
catch (...)
{
// some magic
throw;
}
另一件事要记住的是,当你做捕获一个例外,它通常最好赶const
参考,而不是只是一个参考。
C++没有 '根' 的异常类型所有异常继承,因为C++可以抛出任何东西,包括不能继承的类型;例如'int'。 C++可以抛出任何东西,因为他们没有看到让异常变得不那么普遍的理由。它类似于C++模板; C++模板不依赖于继承,因此比一般依赖继承的Java或C#泛型更通用。 – bames53
某些Windows SEH异常有时可能被'...'发现,但不会被'std :: exception'发现。只有当你疯狂的标志编译,使用推荐/ EHSC(如果可以的话),你会被罚款 –
@MooingDuck –