gpt4 book ai didi

c++ - 从日志格式中解耦异常

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:47:58 24 4
gpt4 key购买 nike

在我的 API 中,我有一个小的异常层次结构,派生自 std::exception .我有一个基类 Exception ,它提供了错误代码、文件、行和函数。其他更具体的异常(exception)来自 Exception .例如,一个派生类添加了一个特定于平台的错误代码,以及一个标识哪个函数返回错误代码的字段。这就像system_error的简化版,但我不能使用 C++11 特性(我一直在使用 VS2005,没有 Boost)。

我需要用我的日志类来记录这些异常。我希望以某种格式记录异常。看了网上的各种论坛,看了Boost's Error and Exception Handling Guidelines ,我不认为what每个异常的函数,或 Exception 中的任何其他虚函数, 是格式化日志记录异常的适当位置。因此我的 what函数只返回类的名称。

在捕获异常时,我经常想捕获非常一般的异常,通常是std::exception ,并将其传递给记录器。我不想经常捕获单个异常,因为我试图防止异常逃逸 API(我的 API 的公共(public)部分在 C 中),并且可能会发生几个异常。我想避免这样的代码:

try { /* blah */ }
catch {DerivedException const& ex) { logger.log(ex); }
...
catch {Exception const& ex) { logger.log(ex); }

所以在我的日志类中,我的 log函数接受 std::exception争论。然后它使用 typeid将参数与各种异常类进行比较,转换为适当的类型,然后调用专门用于该类型异常的日志记录函数。这与描述的技术基本相同 in this other post .

我用 typeid而不是 dynamic_cast因为 dynamic_cast对于任何有效的向下转型都可以成功,并且出于代码维护的目的,我真的不想要我的 if 的顺序 log 中的声明功能很重要。

那么这是一个体面的设计吗?使用 typeid 感觉不对像这样,但我认为我有充分的理由这样做。因为我们主要使用 C 语言,所以我没有看到太多的异常处理“在野外”,所以我没有看到太多关于该主题的方法。是否有其他方法可以将异常与我应该注意的日志格式分离?

编辑:我决定实现的内容
我接受了使用访问者模式的建议,但根据我的情况进行了调整。我想抓 std::exception ,因为这些可以像我自己的一样抛出,但根据异常类型格式化日志消息。

我的每个异常类都派生自我的基础 Exception类并实现虚函数 accept .我创建了一个 ExceptionLogger类,它实现了 ExceptionVisitor提供 visit 的接口(interface)职能。
LogFile类有一个 ExceptionLogger 的实例,以及其 log 的过载接受 std::exception 的函数范围。在 log功能,我试试 dynamic_cast到我的基本类型, Exception .如果成功,我调用 accept异常的函数,否则我调用 ExceptionLogger::visit(std::exception const&)直接发挥作用。自 std::exception没有实现我的 accept功能,我需要 dynamic_cast所以我可以确定是否可以进行更详细的日志记录。

我选择这样做而不是一系列 if语句检查 typeid因为:
  • 这是一个命名的设计模式,我可以将 future 的维护者推荐给
  • 如果维护者添加了源自我的 Exception 的新异常基础,但忘记实现新的 visit该异常的函数,我仍将获得为基础 Exception 实现的日志记录- 文件、行号和函数。

    如果我实现了 if 系列声明,我将不得不退回到 std::exception日志行为,也就是打印出what的结果,或者我可以尝试使用 dynamic_castException .

    当然,在这种情况下,我仍然更喜欢编译器错误。
  • 最佳答案

    一个更简单的解决方案是在中央格式化方法中重新抛出异常(另请参阅 this answer )。然后,您可以在那里捕获每个异常类型并对其进行格式化。

    class Exception : public std::exception {};
    class DerivedException : public Exception {};
    void LogThrownException();

    void DoSomething()
    {
    try
    {
    // Do something, might throw ...
    }
    catch (...)
    {
    LogThrownException();
    }
    }

    void LogThrownException()
    {
    try
    {
    throw;
    }
    // Order is important to catch all derived types.
    // Luckily the compiler should warn, if a type is hidden.
    catch (DerivedException&)
    {
    std::cout << "DerivedException";
    }
    catch (Exception&)
    {
    std::cout << "Exception";
    }
    catch (std::exception&)
    {
    std::cout << "std::exception";
    }
    // ...
    catch (...)
    {
    std::cout << "Unknown\n";
    }
    }

    关于c++ - 从日志格式中解耦异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25941898/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com