c++ - 在 C++ 的异常层次结构中引入额外的基类型?

标签 c++ exception multiple-inheritance

我们的基本情况如下所示:

// 3rd party lib:

namespace ns3p {
  class OperationException : public std::exception; // yes, no `virtual` here
}

// our code:

// wrapper with additional information to the ns3p::OperationException
class ModuleOpException : public ns3p::OperationException;

// our catch sites:
// mostly:
catch (ModuleOpException const& ex) { ...
// but sometimes:
catch (ns3p::OperationException const& ex) { ...

现在,这增加了额外的异常,所有异常都源自 ModuleOpException与来自第 3 方库的任何错误有任何关系,但只是在使用第 3 方库的内容的相同上下文中抛出。

// This indirectly derives from ns3p::OperationException, even though 
// there is *no* underlying OperationException at all. It just thrown "stand alone"
// and caught by ModuleOpException& :
class InvalidXYZException : public ModuleOpExcpetion;

我们现在考虑“反转”层次结构以更好地反射(reflect)实际情况,并且这样做(最初)对其他代码的影响最小。

我们计划这样做:

// new base exception type:
class ModuleBaseException : public virtual std::exception;

// changed to derive both from our base type as well as the 3rd party type:
class ModuleOpException : public virtual ModuleBaseException, public virtual ns3p::OperationException;

// only derives from the base type:
class InvalidXYZException : public virtual ModuleBaseException;

// all catch sites change the catch of `ModuleOpException` to:
catch (ModuleBaseException const& ex) { ...
// and leave the catch ns3p::OperationException alone

这应该有效(应该吗?),除了我不确定第三部分异常的 std::exception 的非虚拟继承有多少type 会把事情搞砸。我认为我们很安全as long as noone tries to catch(std::exception const&) in which case the catch would fail在运行时绑定(bind),因为转换不明确。

这看起来是一个可行的解决方案吗?还是尝试将 non-virtual-std::exception 类型与上述层次结构集成是一个“非常糟糕的主意”?

注意:我们可以更改第 3 方库以使用来自 std 的 virtual “正确”派生的可能性为零(如 0.00%)::异常。


  • 当然,如果之前版本中的任何catch(ns3p::OperationException&)“不小心”捕获了InvalidXYZExecption,这现在会中断,但这是可以接受的.

最佳答案

try...catch 应该发生在异常将被正确处理的地方,或者如果异常将在此时被修改并重新抛出。

使用不同的异常类的目的是为了以不同的方式处理它们。 (我认为这是一个坏主意,打开某种代码会更好,并且您可能仅在极少数情况下才根据类型更改您的操作,例如如果错误是暂时的则重试请求)。

无论如何,我假设第 3 方库用于帮助实现您自己的库。您的库的用户不想知道您用于实现的库的异常。

因此,您应该从您的库的用户那里抽象出来,通过捕获它们中的任何一个并将它们作为您自己的重新抛出,以用户期望的方式。

从您的库中抛出的异常与您的函数的返回值一样都是“契约”的一部分。

因此,用户可能希望捕获 ModuleBaseException 或 ModuleOpException 而不是 ns3p::OperationException。

您自己的代码应该捕获它们,可能会将它们转换为您的 ModuleOpException 类型并抛出它。

关于c++ - 在 C++ 的异常层次结构中引入额外的基类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27824543/

相关文章:

c# - 从实现者调用接口(interface)扩展方法在 C# 中很奇怪

python - 在Python多重继承中,父类使用子定义的变量有多糟糕?

c++ - 设计问题 - 多重继承,C++

python - 在上下文管理器中处理异常

Java自定义Exception错误未报告异常

C++ Builder 如何用 vector 构建动态对象?

C++ 用户输入未注册

java - 在程序完成之前出现异常详细信息?

c++ - VS2012、C++11 和内存泄漏检测(VLD 与 CRTDBG)

c++ - 在Windows上使用va_copy是否安全?