C++ 日志记录类实例标识符

标签 c++ c++11

在我的项目中,一些类被实例化了不止一次。每个类记录一些事件。日志记录方法是在整个项目中使用的通用方法,它使用标准的cout。日志消息包含时间、类名、方法名、变量值和自定义消息。

缺点是日志不是特定于实例的。我不知道是哪个类的实例写了日志。

有没有一种很好的方法可以解决这个问题而不用添加额外的静态成员作为类的实例计数器?我正在使用 boost 和 C++11。也许 boost 有一些帮助。

我能想到的唯一解决方案是将实例地址(this)包含到日志中。

最佳答案

您将需要在某处区分不同的类,这些是一些选项(都依赖于某种 ​​ID):

  1. 添加一些额外的静态变量。
    这不是您的选择,但在我看来,如果您的目标是可读性,这是最好的方法。
  2. 按照您的建议使用this:
    这显然会生成唯一的 ID,但随着地址长度的增加,它们往往不可读且难以区分(因为在冗长的地址字符串中可能只有一两个字符不同)。此外,地址可能会在应用程序的每次运行之间发生变化(尤其是在使用 ASLR 时),因此您将无法看到哪个确切的实例创建了哪一行输出(如果需要的话)。
  3. 使用this散列值:

老实说,我看不出与 2) 有什么不同,但它可能会引发一些进一步的想法。一些丑陋的 hack 可能看起来像这样:

#include <iostream>
#include <functional>
#include <cstddef>

class Logger
{
public:
    static void log(void* ptr)
    {
        using hash_type = std::uintptr_t;
        std::cout << std::hash<hash_type>{}(reinterpret_cast<hash_type>(ptr))
            << " logged something..." << std::endl;
    }
};

你也可以考虑specializing std::hash为您的类(class)并在日志输出中使用它。如果实现得当,这将消除在不同运行之间更改地址的问题。

  1. 在构造过程中生成一个 ID(例如,通过将一些标识符传递给构造函数):
    这实际上不是一个选项,因为您没有证据或无法控制为每个类生成唯一 ID - 除非您使用某种(抽象)工厂来访问私有(private)构造函数或某种全局注册表(见下文)。
  2. 使用一些辅助实用程序来注册您的日志记录类并生成唯一 ID(类似于注册类)。
    出于简单的日志记录目的,恕我直言,这是膨胀的,与 1 相比不会增加任何值)。

结论: 如果考虑到人类的可读性,我会选择选项 1),如果您只是想要一些数字来区分日志消息(例如,用于管道和过滤),我会选择选项 2)。

关于C++ 日志记录类实例标识符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50502067/

相关文章:

c++ - 通过继承的类模板 SFINAE

c++ - opencv估计RigidTransform : How to get global scale?

c# - 将 vector<unsigned char> {1,2,3} 转换为字符串 "1-2-3"AS DIGITS

c++ - Dart 编译错误 - 代码库中的奇怪代码片段

c++ - 将 C++ 接口(interface)写入动态分配的 C 结构

c++ - std::forward_list 成员可以实现为静态的吗?

c++ - uniform_real_distribution operator() 编译错误

c++ - 避免依赖关系使我的VS解决方案中的项目数量激增

c++ - 如何索引到 C++ shared_ptr/unique_ptr 数组?

c++ - GMOCK如何为函数参数赋值