在C ++中,如何使用单例来确保每个类都有唯一的整数ID?

时间:2010-01-31 18:59:10

标签: c++ class singleton unique-id

我有一堆C ++类。

我希望每个班级都有类似的东西:

static int unique_id;

同一个类的所有实例应该具有相同的unique_id;不同的类应该有不同的unique_id。

执行此操作的最简单方法似乎是通过类线程化单例。

但是,我不知道什么时候静态类成员/事件发生在main之前。

(1)如果您的解决方案不涉及使用单身,那也没关系

(2)如果你有一个解决方案给我一个:

int unique_id(); 

也没关系。

谢谢!

6 个答案:

答案 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)

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> {
  // ...
};

答案 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 
*/

我希望这有帮助!请告诉我任何问题。