【发布时间】:2014-02-11 12:17:02
【问题描述】:
对于错误处理,异常对我来说是个问题,因为我的代码将是一个动态链接库。此外,我认为异常只应在特殊情况下使用。但是我会遇到一些可能发生错误的情况,但并不例外。另一个问题是我的库将从 C# 调用。所以在这里对所有错误使用异常似乎不是正确的选择。
但我发现 std::error_code 和 std::error_category 的概念非常令人愉快,并希望在我的应用程序中使用它。不过,我还想提供某种堆栈跟踪以发现错误。
考虑一个例子: 用户想要从数据库加载域对象。要加载此域对象,应用程序需要从不同的表中加载行。假设找不到所需的行之一。在这种情况下,数据库层会产生一些 "not found" 错误。如果我将此错误全部传播给用户,则错误消息将不会很有帮助,因为没有人知道 what 没有找到。同样,如果每一层都处理下层的错误并生成相应的新错误,抽象出低级错误,我最终会得到类似“无法从数据库加载”之类的东西,这又不是很有帮助。我想要的是两者兼得。也就是说,每一层都抽象了它从任何较低级别获得的错误,以便能够向最终用户显示描述性消息,但同时我不想丢失有关低级别错误的信息。 所以我想要一个错误堆栈跟踪之类的东西。
我考虑从 std::error_code 派生并使用指向底层 std::error_code 的指针和获取所有这些底层对象的方法来扩展类。但是,我不确定这种技术是否是一个好主意,因为我读到在设计 std::error_code 以使其高效时已非常小心。
我们希望 error_code 是一种无需切片且无需堆分配即可复制的值类型,但我们还希望它具有基于错误类别的多态行为。
编辑 我现在认为这种技术也会引入切片问题,不是吗?
编辑 2 我现在想通过从 std::error_code 派生来实现它。我的派生类将有一个 boost::optional ,而不是一个指针,什么地方需要堆分配。这样,内部错误代码可以简单地通过复制在堆栈上创建。 boost::optional 可以正确表示不存在的内部错误代码。切片仍然是一个问题,但我想这是可以忽略的,因为将派生类的实例分配给 std::error_code 变量的情况是不必要的,即使发生这种情况,我只会丢失有关内部错误代码的信息。此外,我可以提供从 std::error_code 到没有内部错误代码的派生类的转换。
编辑 3 我没有想到不可能有一个包含 boost::optional 的类。所以现在我看不到在堆上没有分配的情况下我想要的任何可能性。
【问题讨论】:
-
为什么不用
inner_exception()方法定义自己的std::exception派生异常类来返回内部异常(源自较低级别)?您的 UI 甚至可能会捕捉到business_exception,但通过inner_exception()导航,您可能会记录每一层中发生的所有事情(好吧,如果您想这样做,可能出于安全原因不要公开基本细节)。 -
哦,顺便说一句,IMO
std::error_code和std::error_category不适合您的场景。应用程序应该使用异常来通知错误,错误代码是非 C++ 环境的遗产(例如操作系统 API 或设备驱动程序)。在这种情况下,IMO 您应该围绕该函数创建一个包装器,用std::error_code封装其错误代码;使用 C++ish 接口公开它们,然后使用异常管理应用程序中的错误(使用您自己的异常,使用error_code()成员获取低级错误代码(如果有)。 -
我不能使用异常,因为我写的代码应该是动态链接库
-
如果所有涉及的模块都是 C++ 并且它们使用相同的编译器,则可以使用它们。如果没有,那么即使
std::error_code也不起作用(你必须回到int)。如果出于任何原因您想依赖错误代码(但它们应该仅用于兼容性,IMO),那么您可以应用相同的技术(error_code是非密封类) -
正如我所提到的,例外不是我的选择。
标签: c++ c++11 error-handling