定义自己的异常类的最佳实践是什么?

34

我有一些特殊的异常情况需要抛出和捕获,因此我希望定义自己的异常类。

那么最佳实践是什么?我应该继承自std::exception还是std::runtime_error

5个回答

27

是的,继承std::runtime_error或者其他标准异常类例如std::logic_errorstd::invalid_argument等等,这样做是一个好的实践方法,具体取决于所涉及的异常类型。

如果所有异常都以某种方式从std::exception继承,那么通过catch(const std::exception &e) {...}可以轻松捕获所有常见错误。如果您有几个独立的层次结构,则会变得更加复杂。从专门的异常类继承可以使这些异常携带更多信息,但这是否真正有用取决于您如何处理异常。


7
通过 const 引用捕获:catch(std::exception const& e) - Martin York
同一天采纳了使用常量引用捕获的建议。 - Wolf
同一天采纳了使用常量引用进行捕获的建议。 - undefined

7

我不是C++开发人员,但我们在C#代码中做的一件事是为我们的框架创建一个基类异常,然后在构造函数中记录抛出的异常:

  public FrameworkException(string message, Exception innerException)
      : base(message, innerException)
  {
      log.Error(message, innerException);
  }

  ...

任何派生的异常只需要调用它的基本构造函数,我们就可以在整个过程中得到一致的异常记录。虽然不是很重要,但是很有用。

你必须小心处理花哨的异常,特别是当异常本身的构造可能会引发异常时。 - Herbert

3

当异常被放置在一些作用域内时,是非常好的。例如,类Manipulation可以在异常类Error内声明。

并且像这样捕获它们:

catch ( const Manipulation::InputError& error )
catch ( const Manipulation::CalculationError& error )

在这种情况下,它们可以只是空类,没有任何额外的错误信息,除非您的设计允许这些异常飞得更高,在那里您可以捕获所有标准异常。

2

在我看来,从std::exception继承与否并不重要。对我来说,定义异常最重要的是:

  1. 异常类的名称有用且清晰。
  2. 清楚地记录(编写注释),函数或类方法何时会抛出异常。在我看来,这是异常处理中最大的失败点。

1

这并没有太大的区别,因为std::runtime_error也继承自std::exception。你可以认为运行时错误更多地传达了关于异常的信息,但在实践中,人们经常只从基本异常类派生。


如果您通过子类型处理(即捕获)异常,但仍希望将std::string消息与其一起传递,那么使用std::runtime_error构建异常是否更容易呢?这样做是否能够在定义子类时实现零规则? - Wolf
如果您通过子类型处理(即捕获)异常,但仍希望将std::string消息与其一起传递,那么使用std::runtime_error构建异常会不会更容易呢?这样做是否可以在定义子类时实现零规则? - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接