std::exception 和 "..." 之间的区别


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
}

最新更新