std :: exception和“...”之间的区别

时间:2013-07-01 15:12:47

标签: c++ exception

A:      catch(...)  
B:      catch(std::exception& e)

问题是什么可以捕获但B不能。

为什么在C ++中没有引入可以捕获任何内容的通用根异常

---补充道 对不起,我应该说我在C ++中理解你可以抛出任何类型的int,但除此之外,还有什么可以抛出?

我的问题是我试图找到从代码抛出的异常,它可以被A但不是B捕获。这个异常绝对不是像“int”这样的类型。它必须是系统异常或内存违规。我只是想知道那可能是什么。

3 个答案:

答案 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
}