A: catch(...)
B: catch(std::exception& e)
问题是A能抓到什么,而B不能。
以及为什么C++没有引入可以捕获任何东西的通用根异常
---添加对不起,我应该说我理解C++你可以抛出任何像int这样的类型,但除此之外,还有什么可以扔的?
我的问题是我试图找到从代码中抛出的异常,可以由 A 捕获,但不能由 B 捕获。这个例外绝对不是像"int"这样的类型。它必须是系统异常或内存冲突之类的事情。我只是想知道那可能是什么。
catch (...)
是一个所谓的"全部捕获"块。它将捕获任何C++异常。
catch(std::exception& e)
将仅捕获从 std::exception
派生的异常。
下面是一个异常示例,该异常将由 catch-all 调用,但不是第二个版本:
throw 42;
这对你来说可能看起来很奇怪,事实确实如此。 重要的是要意识到,任何东西都可以作为C++例外抛出——而不仅仅是exception
或从exception
派生的东西。 正如@bames53在注释中提到的,没有像其他一些语言那样派生所有异常的根异常类型。
同样重要的是要注意,包罗万象的块很容易被滥用。 事实上,作为一般的经验法则,最好假设所有包罗万象的块都是程序缺陷。 当然,编程中没有"总是",但是当您学习使用异常时,这是一个安全的假设。
包罗万象的块之所以是邪恶的,是因为它们通常的使用方式。 通常,一个天真的程序员会写一个包罗万象的,试图捕捉任何编程错误,然后,关键是,继续让程序运行,就好像什么都没发生过一样。 这是一场等待发生的灾难。 程序状态现在不确定。 有些东西,某处出了问题。 您不能安全地忽略异常并继续前进,就像一切都很好一样。 即使您的程序继续运行,也可能在某处存在微妙的堆损坏,这会掺杂程序的计算或其输出。 当堆损坏确实发生时,作为程序员,您所能希望的最好的事情就是立即崩溃。 这样,您就可以在损坏时获取调用堆栈和转储文件,并查找并解决问题。 但是,当你有一个包罗万象的地方时,你就失去了这种腐败发生的所有背景。 几乎不可能在代码中找到真正的缺陷。
当然,捕获所有处理程序也有有效且有价值的用途。 最常见的一种是编写一个全局异常处理程序,然后重新throw
异常。 此全局处理程序可以启动某种错误日志记录,可能是通过记录错误本身,或者生成一个外部程序,该程序在失败程序之外执行日志记录。 通过重新引发异常,可以让委托有机会处理可以处理的异常,同时允许无法处理的异常终止程序。
重新引发异常很简单。 只需调用throw
,无需参数,例如:
catch (...)
{
// some magic
throw;
}
要记住的另一件事是,当您捕获异常时,通常最好捕获const
引用,而不仅仅是引用。
的回答是在其(公共(继承层次结构中没有std::exception
的任何内容:
#include <exception>
#include <iostream>
int main()
{
try
{
throw false;
}
catch(std::exception& e)
{
std::cout << "Caught std::exception" << std::endl;
}
catch(...)
{
std::cout << "Caught something else" << std::endl;
}
return 0;
}
输出:
抓到了别的东西
int
s怎么样?
try {
throw 123;
} catch (std::exception &e) {
// this won't catch
} catch (...) {
// this will catch
}