区别:std :: runtime_error与std :: exception()


127

std::runtime_error和之间有什么区别std::exception?每种用途的适当用途是什么?为什么它们与众不同?

Answers:


152

std::exception是唯一目的是用作异常层次结构中的基类的类。它没有其他用途。换句话说,从概念上讲,它是一个抽象类(即使在该术语的C ++含义中没有将其定义为抽象类)。

std::runtime_error是一个更专业的类,从派生而来std::exception,旨在在发生各种运行时错误抛出。它有双重目的。它可以通过自身被抛出,或者它可以作为一个基类各种更专门类型的运行时错误异常,如std::range_errorstd::overflow_error等你可以定义自己的异常类从降std::runtime_error,以及你可以定义自己的异常源自的类std::exception

就像std::runtime_error标准库包含的一样std::logic_error,它也是从std::exception

具有这种层次结构的目的是使用户有机会使用C ++异常处理机制的全部功能。由于'catch'子句可以捕获多态异常,因此用户可以编写'catch'子句来捕获异常层次结构的特定子树中的异常类型。例如,catch (std::runtime_error& e)将从std::runtime_error子树中捕获所有异常,让所有其他异常通过(并进一步飞向调用堆栈)。

PS设计一个有用的异常类层次结构(将使您仅在代码的每个点上都捕获感兴趣的异常类型)是一项艰巨的任务。您在标准C ++库中看到的是该语言作者为您提供的一种可能的方法。如您所见,他们决定将所有异常类型分为“运行时错误”和“逻辑错误”,然后让您继续处理自己的异常类型。当然,还有其他方法可以构造该层次结构,这可能更适合您的设计。

更新:可移植性Linux vs Windows

正如Loki Astari和unixman83在下面的答案和注释中指出的那样,exception根据C ++标准,该类的构造函数不接受任何参数。Microsoft C ++具有在exception类中接受参数的构造函数,但这不是标准的。本runtime_error类有一个构造回吐参数(char*这两个平台,Windows和Linux上)。为了便于携带,更好地使用runtime_error

(请记住,只是因为您的项目规范说您的代码不必在Linux上运行,并不意味着它永远不必在Linux上运行。)


1
谢谢。好答案。虽然我想知道是否有需要使用不同类型的异常...只是一个想法。
sivabudh's

1
如果存在可以从中重新恢复异常的功能,则可以使用另一种类型的异常,因为我们可以使用异常处理机制将异常定向到将尝试并纠正问题的处理程序。如果没有恢复的机会,那么标准例外之一就可以了。
马丁·约克

1
顺便说一句:在任何地方都没有规则可以迫使您从中推导std::exception。当然,所有std事物都抛出该类的派生类,但是绝对没有理由仅抛出std::exception派生对象。
rubenvb 2014年

1
@rubenvb我不知道,但是如果仅抛出从异常派生的类的对象,我想它将清除代码以供将来维护。示例:我想找出在我的代码库中实现了哪些自定义异常,并搜索从异常派生的类。
this.myself 2014年

21

std::exception应该被视为(注意被考虑的)标准异常层次结构的抽象基础。这是因为没有传递特定消息的机制(为此您必须派生和专门化what())。没有什么可以阻止您使用std :: exception,对于简单的应用程序,可能只是您所需要的。

std::runtime_error另一方面,具有接受字符串作为消息的有效构造函数。当what()调用时,将返回const char指针,该指针指向一个C字符串,该字符串与传递给构造函数的字符串相同。

try
{
    if (badThingHappened)
    {
         throw std::runtime_error("Something Bad happened here");
    }
}
catch(std::exception const& e)
{
    std::cout << "Exception: " << e.what() << "\n";
} 

1
感谢您的回答马丁。但是,我使用std :: exception()的方式与您上述相同。即std :: exception()构造函数也可以采用std :: string()或const char *。
sivabudh

14
不符合标准。std :: exception具有一个不带参数的构造函数。使用接受std :: string或C-String的版本是不可移植的。
马丁·约克

10
因为有了微软,我习惯了投掷std::exception(std::string)。现在我意识到,std::runtime_error如果我想让我的代码在Linux(GCC)中运行,我必须抛出。
unixman83 2011年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.