C ++中的标准或自定义异常?

时间:2011-01-20 13:29:50

标签: c++ exception standards

对于库代码,更好的做法是创建和抛出自定义异常类(library :: Exception),还是只抛出标准异常(runtime_error,invalid_argument等)?

4 个答案:

答案 0 :(得分:27)

通常更好地专门化(继承)标准异常并抛出它。

这样就可以通过捕获std::exception将其作为常规异常捕获,但如果需要更专业的代码,也可以专门捕获自定义异常类型。

另请参阅此C++Faq了解要投掷的内容。

答案 1 :(得分:7)

通常,您应该在stdexcept标头或其子类中抛出类的实例。什么类确切有意义取决于具体问题。我认为抛出“类别类”std::logic_errorstd::runtime_error的实例很少有用,因为它们没有固有的含义;它们用于区分可能发生例外的两种主要情况:

  • 如果调用了std::logic_error的子类,则应该抛出它的子类,但并不是所有前置条件都满足。例外是调用者的错误,因为它未能提供必要的前提条件。对于此类别,您通常必须在投掷和未定义的行为之间进行选择;它是健壮性和有效性之间的权衡(例如std::vector::at()std::vector::operator[]。这些例外通常无法处理;它们是程序中的错误的结果。

  • 如果满足所有前提条件但函数不能满足后置条件或由于程序控制之外的原因而打破不变量,则函数应抛出std::runtime_error的子类(例如,文件不是存在,网络连接丢失,或者没有足够的内存可用)。通常应该处理这些例外情况。

我认为可用的逻辑错误类(例如invalid_argument)通常足够好,因为如果它们被引发,代码通常必须修复,并且没有理由精心设计的处理程序。另一方面,标准库中的运行时错误类本质上不太灵活,主要涵盖标准库本身必须抛出异常的区域。对于您的应用程序,您几乎应该始终从这些运行时错误类继承。例如,如果构造函数无法分配资源,则管理操作系统资源 X 的类应该抛出X_creation_error继承自std::runtime_error

多个虚拟继承通常对异常类很有用。您可以从std::runtime_error或其他stdexcept类,特定于您的库的某些“标记类”以及boost::exception继承,以获得Boost.Exception library的其他好处。强烈建议使用Boost.Exception教程,尤其是Exception types as simple semantic tagsUsing virtual inheritance in exception types

答案 2 :(得分:2)

恕我直言自定义例外。您图书馆的客户会对此表示赞同。他会知道什么是正确的例外。

答案 3 :(得分:2)

根据经验,您需要的不仅仅是极少数异常类。

在我的大部分代码中(主要是数字代码 - 如果你做例如.IO,情况不同),我抛出标准的exeptions(runtime_errorinvalid_argument,...)因为它们倾向于表示无法轻易恢复的内容(可能invalid_argument除外),并且可能不会被用户代码捕获(除非在顶层向用户抛出消息框)。

如果存在一些旨在被典型用户代码捕获的异常,例如。 bad_custom_castbad_market_data_identifier,而不是冒泡到主要(如数字例程中的失败,或bad_alloc),我创建了一个自定义类。但实际上这很少见。