C++日志记录类实例标识符
C++ logging class instance identifier
在我的项目中,有些类被实例化了不止一次。每个类记录一些事件。日志记录方法是在项目周围使用的通用方法,它使用标准cout。日志消息包含时间、类的名称、方法的名称、变量值和自定义消息。
缺点是日志不是特定于实例的。我不知道该类的哪个实例编写了日志。
有没有一种很好的方法来解决此问题,而无需向类添加额外的静态成员作为实例计数器?我正在使用提升和 C++11。也许提升有一些可能会有所帮助的东西。
我能想到的唯一解决方案是将实例地址(this(包含在日志中。
您需要在某处区分不同的类,以下是一些选项(都依赖于某种 ID(:
- 添加一些额外的静态变量.
不是您的选择,但在我看来,如果您的目标是可读性,这是最好的方法。 - 按照您的建议使用
this
:
这显然会生成唯一的 ID,但它们往往不可读且难以随着地址长度的增加而区分(因为在冗长的地址字符串中可能只有一个或两个字符不同(。此外,地址可能会在每次运行应用程序之间更改(尤其是在使用 ASLR 时(,因此您将无法看到哪个确切的实例创建了哪一行输出(如果需要(。 - 使用
this
并对值进行哈希处理:
老实说,我认为与 2 没有太大区别(,但它可能会引发一些进一步的想法。一些丑陋的黑客可能看起来像这样:
#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;
}
};
您还可以考虑为类专门使用std::hash
,并在日志记录输出中使用它。如果实施得当,这将消除在不同运行之间更改地址的问题。
- 在构造过程中生成一个
- ID(例如,通过将一些标识符传递给构造函数(:
这不是一个真正的选择,因为您没有证据或控制为每个类生成唯一 ID - 除非您使用某种可以访问私有构造函数或某种全局注册表的(抽象(工厂(见下文(。 - 使用一些帮助程序实用程序,在其中注册日志记录类并生成唯一 ID(类似于注册类(.
出于简单的日志记录目的,恕我直言,这是臃肿的,与 1 相比不会增加任何值(。
结论:我会选择选项 1( 如果人类的可读性是值得关注的,以及 2( 如果您只是想要一些数字来区分日志消息(例如用于管道和过滤(。
您可以通过这样的CRTP 适配器轻松生成 ID(如果您可以稍微修改一下类(
template<typename T>
struct enable_id
{
int id = global_id++;
private:
static int global_id;
};
template<typename T>
int enable_id<T>::global_id = 0;
class foo : public enable_id<foo>
{
};
template<typename T>
void log(const T& t)
{
// if is_base_of
std::cout << t.id << std::endl;
}
修复 problom 的更简单方法是打印地址以指示它是哪个对象。 如下:
cout<<static_cast<void*>(this)<<endl;
或者输出一些功能。
我通常有一个受保护的类成员,其中包含我所有类层次结构的根目录下的实例创建时间,至少在调试阶段是这样。对多线程应用程序也非常有帮助。
将此时间转换为您想要的任何时间 - 字符串、毫秒、纪元时间 - 并且每个实例都有一个唯一的 ID。
如果只有几个类实例,我建议您引入一个字符串成员,并在对象创建期间使用唯一名称对其进行初始化。它将帮助您读取日志。默认情况下,可以使用对象的地址对其进行初始化。
- 从C++实例化QML
- 在全局变量中保存类的实例以重新创建类(创建"backup")
- OpenGL - 在抛出"__gnu_cxx::recursive_init_error"实例后终止调用?
- 如何在c++中为模板函数实例创建快捷方式
- 在C++中,是否可以基于给定的标识符创建基类的新实例,反之亦然
- 设计一个只能由特定类实例化的类(如果可能的话,通过make_unique)
- 如何创建一个空的全局类并在启动时实例化它
- 无法创建抽象类的实例
- #ifdef和未声明的标识符
- 多个文件的内存分配错误"在抛出 'std :: bad_alloc' what (): std :: bad_alloc 的实例后终止调用" [C++]
- 在两个类中共享相同的函数调用,并在不需要时避免空实例化
- 我收到以下错误:抛出'std::bad_alloc'实例后终止调用
- C++日志记录类实例标识符
- 用户创建的类对象实例化的未申请标识符
- 没有成员作为唯一标识符的两个类实例的比较
- 宏为模板类静态实例生成有效的标识符
- 使用标准类型的动态类型信息实例化标识符
- "未声明的标识符",同时尝试在 C++ 中创建实例
- 尝试创建结构实例时C++未声明的标识符
- 在不使用标识符的情况下重复类实例化