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