在 C++ 中,如何使用单例来确保每个类都有唯一的整数 ID?
Posted
技术标签:
【中文标题】在 C++ 中,如何使用单例来确保每个类都有唯一的整数 ID?【英文标题】:in C++, how to use a singleton to ensure that each class has a unique integral ID? 【发布时间】:2011-01-11 11:41:31 【问题描述】:我有一堆 C++ 类。
我希望每个班级都有类似的东西:
static int unique_id;
同一个类的所有实例都应该有相同的unique_id;不同的类应该有不同的unique_id。
执行此操作的最简单方法似乎是将单例线程通过类。
但是,我不知道什么时候调用静态类成员/在 main 之前发生的事情。
(1) 如果你有一个不涉及使用单例的解决方案,那也没关系
(2) 如果你有一个解决方案可以给我一个:
int unique_id();
那也不错。
谢谢!
【问题讨论】:
您需要控制值还是只是想区分不同类别的对象?可以只使用 typeid 关键字作为区分符吗? 我不需要控制值(不使用它进行序列化)。我需要区分不同类的对象。 [特别是模拟 Haskell 的 Data 字。] 这就是std::type_info
(typeid
运算符的结果)的发明目的。它甚至具有用作地图键的机制。
小心使用此类 ID 在机器之间交换信息,或将对象序列化到文件或从文件中序列化对象。一台机器生成 ID 的方式可能与另一台机器不同。如果您重新组织代码,生成的 ID 甚至可能在同一台机器上发生变化。
【参考方案1】:
有一个在每次创建时递增其 ID 的类。然后将该类用作每个应该具有 ID 的对象中的静态字段。
class ID
int id;
public:
ID()
static int counter = 0;
id = counter++;
int get_id() return id;
;
class MyClass
static ID id;
public:
static int get_id()
return id.get_id();
;
【讨论】:
-1 类的每个实例都具有相同的值。不同的类有不同的值。 @anon,如果您不理解解决方案,请不要投反对票,要求澄清。 你是对的。这是我搞砸了。你可以“编辑”你的帖子,这样我就可以投票给你了吗? (投票太旧,无法更改)。 @anon,没有冒犯,只是不要过早:) @Korenl 感谢您回来指出我误解了(而不是默默地无视我);你的解决方案很酷。【参考方案2】:以Kornel's solution 为基础:
class id_impl
private:
id_impl()
static int get_next_id()
static int counter = 0;
return ++counter;
template< class T >
friend class id_base;
;
template< class T >
class id_base : private id_impl
public:
static int get_id() return id;
private:
static int id;
;
template< class T >
int id_base<T>::id id = get_next_id();
像这样使用它:
class my_class : public id_base<my_class>
// ...
;
【讨论】:
额外的复杂功能会给您带来什么? 这只是id_base
的创建者 的麻烦。对于它的用户来说,这是一种简化:他们只需要从类派生而不必将get_id()
成员复制到他们的所有类中。
啊,好的。这是为了节省大量繁琐的工作而奇怪地重复出现的模板习语。
轻微吹毛求疵,ID<T>::id_base id
应该是int id_base<T>::id
。 :)
你的代码没有编译,codepad.org/QipqYlPE你需要改 int id_base实际上这与 RTTI 非常相似。为了实现 (2),可以利用 C++ 的内置 RTTI。在*this
上调用typeid
,并将typeinfo的地址作为唯一ID。
缺点:a) ID 不是固定的(重新编译会更改它们),b) 信息仅在给定类的实例时可用,c) 它很丑。
你为什么要这个?
【讨论】:
【参考方案4】:C++ 已经内置了这个。
您可以使用typeid
运算符返回type_info
类。 type_info:name()
将返回类的(唯一)名称。
【讨论】:
您必须启用 RTTI。 如何获取整数而不是字符串? @anon,type_info 不幸的是没有这样的字段(真的很遗憾)。您可以将 type_info 地址类型转换为整数,但这将是一个糟糕的解决方案。 小心。 TTBOMK,std::type_info::name()
的结果未指定。虽然我知道的所有实现都返回了一些有意义的东西,但我认为标准并没有强制要求。实现可以返回 "foo"
或空字符串,但仍符合标准。【参考方案5】:
首先,为什么?在任何情况下,您都可以轻松地手动设置 ID:
template <int id>
struct base enum unique_id = id ; ;
class foo: public base<5> ... ;
class bar: public base<10> ... ;
然后
foo x;
bar y;
assert(x.unique_id == 5);
assert(y.unique_id == 10);
当然,您必须手动跟踪每个类的 ID;此时,我会问原来的问题:为什么?
【讨论】:
【参考方案6】:我最近发现Kornel's solution 中的sbi's version 非常有用。谢谢你们两位提供答案。但是,我想进一步扩展解决方案,以便可以轻松创建多种类型的 ID,而无需为每个新类型创建一对单独的 id_impl 和 id_base 类。
为此,我对 id_impl 类进行了模板化,并向 id_base 添加了另一个参数。结果被封装在一个头文件中,该文件包含在任何想要添加新 ID 类型的地方:
//idtemplates.h
template< class T >
class GeneralID
private:
GeneralID()
static int GetNextID()
static int counter = 0;
return ++counter;
template< class T, class U >
friend class GeneralIDbase;
;
template< class T, class U >
class GeneralIDbase : private GeneralID < T >
public:
static int GetID() return ID;
private:
static int ID;
;
template< class T, class U >
int GeneralIDbase<T, U>::ID = GetNextID();
对于我的应用程序,我希望几个抽象基类具有与之关联的 ID 类型。因此,对于 GeneralIDbase 模板的每个实例,指定的类型是:正在声明的派生类的抽象基类,以及正在声明的派生类。
以下 main.cpp 是一个示例:
//main.cpp
#include<iostream>
#include<idtemplates.h>
using namespace std;
class MyBaseClassA ;
class MyBaseClassB ;
class MyClassA1 :public MyBaseClassA, public GeneralIDbase<MyBaseClassA, MyClassA1> ;
class MyClassA2 :public MyBaseClassA, public GeneralIDbase<MyBaseClassA, MyClassA2> ;
class MyClassB1 :public MyBaseClassB, public GeneralIDbase<MyBaseClassB, MyClassB1> ;
class MyClassB2 :public MyBaseClassB, public GeneralIDbase<MyBaseClassB, MyClassB2> ;
int main()
MyClassA1 objA1;
MyClassA2 objA2;
cout << "objA1.GetID() = " << objA1.GetID() << endl;
cout << "objA2.GetID() = " << objA2.GetID() << endl;
MyClassB1 objB1;
MyClassB2 objB2;
cout << "objB1.GetID() = " << objB1.GetID() << endl;
cout << "objB2.GetID() = " << objB2.GetID() << endl;
cin.get();
return 0;
这段代码的输出是
/*
objA1.GetID() = 1
objA2.GetID() = 2
objB1.GetID() = 1
objB2.GetID() = 2
*/
我希望这会有所帮助!如有任何问题,请告诉我。
【讨论】:
以上是关于在 C++ 中,如何使用单例来确保每个类都有唯一的整数 ID?的主要内容,如果未能解决你的问题,请参考以下文章