A: catch(...)
B: catch(std::exception& e)
问题是什么可以捕获但B不能。
为什么在C ++中没有引入可以捕获任何内容的通用根异常
---补充道 对不起,我应该说我在C ++中理解你可以抛出任何类型的int,但除此之外,还有什么可以抛出?
我的问题是我试图找到从代码抛出的异常,它可以被A但不是B捕获。这个异常绝对不是像“int”这样的类型。它必须是系统异常或内存违规。我只是想知道那可能是什么。
答案 0 :(得分:29)
catch (...)
是一个所谓的“全部捕获”块。它将捕获任何 C ++异常。
catch(std::exception& e)
将捕获仅从std::exception
派生的 个例。
以下是catch-all调用的异常示例,但不是第二个版本:
throw 42;
这对你来说可能有些奇怪,而且确实如此。要认识到的重要一点是,任何都可以作为C ++异常抛出 - 而不仅仅是exception
或从exception
派生的东西。正如@ bames53在评论中提到的那样,没有根异常类型可以导出所有异常,就像其他语言一样。
同样重要的是要注意抓住所有块很容易被滥用。事实上,作为一般的经验法则,最好假设所有的catch-all块都是程序缺陷。当然,编程中没有“总是”,但是当你学习使用异常时,这是一个安全的假设。
catch-all块是Evil的原因在于它们通常如何使用。通常,一个天真的程序员会编写一个catch-all来尝试捕获任何编程错误,然后,批判性地,继续让程序运行,好像什么也没发生。这是一场等待发生的灾难。程序状态现在是不确定的。某事,某个地方出了问题。你无法安全地忽略异常并继续前进,就像一切都很好。即使您的程序确实继续运行,也可能存在某个细微的堆损坏,这会破坏程序的计算或输出。当堆损坏确实发生时,你作为程序员所希望的最好的事情是立即崩溃。这样,您可以在损坏点获取调用堆栈和转储文件,并找到并修复问题。但是当你有一个全面的时候,你已经失去了发生这种腐败的所有背景。几乎不可能在代码中找到真正的缺陷。
当然,catch all处理程序的有效和有价值的用途。一个最常见的是编写一个全局异常处理程序,然后重新throw
例外。这个全局处理程序可以启动某种故障记录,可能是通过记录错误本身,或者产生一个外部程序来执行故障程序之外的日志记录。通过重新抛出异常,您可以为代理提供处理可以处理的异常的机会,同时允许无法处理的异常终止程序。
重新抛出异常很容易。只需在没有参数的情况下调用throw
,如:
catch (...)
{
// some magic
throw;
}
要记住的另一件事是,当您捕获异常时,通常最好捕获const
引用,而不仅仅是引用。
答案 1 :(得分:2)
简短回答是(公共)继承中没有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;
}
输出:
Caught something else
答案 2 :(得分:1)
int
怎么样?
try {
throw 123;
} catch (std::exception &e) {
// this won't catch
} catch (...) {
// this will catch
}