我有一堆C ++类。
我希望每个班级都有类似的东西:
static int unique_id;
同一个类的所有实例应该具有相同的unique_id;不同的类应该有不同的unique_id。
执行此操作的最简单方法似乎是通过类线程化单例。
但是,我不知道什么时候静态类成员/事件发生在main之前。
(1)如果您的解决方案不涉及使用单身,那也没关系
(2)如果你有一个解决方案给我一个:
int unique_id();
也没关系。
谢谢!
答案 0 :(得分:9)
有一个类可以在每次创建时增加它的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 :(得分:4)
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> {
// ...
};
答案 2 :(得分:3)
实际上这与RTTI非常相似。为了实现(2),可以利用C ++的buildin RTTI。在typeid
上调用*this
,并将typeinfo的地址作为唯一ID。
Conss:a)ID不是固定的(重新编译会改变它们),b)信息仅在给定类的实例时可用,c)它很难看。
你为什么要这个?
答案 3 :(得分:1)
首先,为什么?在任何情况下,您都可以轻松手动设置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;在这一点上,我会问原来的问题:为什么?
答案 4 :(得分:1)
C ++已经内置了这个。
您可以使用typeid
运算符返回type_info
类。 type_info:name()
将返回该类的(唯一)名称。
答案 5 :(得分:1)
我最近发现sbi's version Kornel's solution非常有用。谢谢你们提供答案。但是,我想进一步扩展解决方案,以便可以轻松创建几种类型的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
*/
我希望这有帮助!请告诉我任何问题。