в C ++, как использовать синглтон, чтобы каждый класс имел уникальный интегральный идентификатор? - PullRequest
4 голосов
/ 31 января 2010

У меня есть куча классов C ++.

Я хочу, чтобы у каждого класса было что-то вроде:

static int unique_id;

Все экземпляры одного и того же класса должны иметь одинаковый уникальный_идентификатор; разные классы должны иметь разные уникальные идентификаторы.

Простейший способ сделать это, по-видимому, состоит в том, чтобы пропустить один класс через классы.

Тем не менее, я не знаю, что называется, когда для статических членов класса / вещей, которые происходят до main.

(1) если у вас есть решение, не предусматривающее использование синглтона, это тоже хорошо

(2) если у вас есть решение, которое дает мне:

int unique_id(); 

это тоже хорошо.

Спасибо!

Ответы [ 6 ]

9 голосов
/ 31 января 2010

Имейте класс, который увеличивает его 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();
    }
};
4 голосов
/ 31 января 2010

Опираясь на Решение Корнеля :

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> {
  // ...
};
3 голосов
/ 31 января 2010

На самом деле это очень похоже на RTTI. Для достижения (2) можно использовать встроенный в CTI RTTI. Позвоните typeid на *this и получите адрес typeinfo в качестве уникального идентификатора.

Conss: a) идентификаторы не являются фиксированными (перекомпиляция изменила бы их), и b) информация доступна только для экземпляра класса, c) она ужасна

Зачем тебе это?

1 голос
/ 30 июля 2012

Недавно я нашел версию sbi из решение Корнела , которое очень полезно. Спасибо вам обоим за предоставленные ответы. Однако я хотел бы расширить решение, чтобы несколько типов идентификаторов можно было легко создавать без создания отдельной пары классов id_impl и id_base для каждого нового типа.

Для этого я шаблонизировал класс id_impl и добавил еще один аргумент в id_base. Результат инкапсулируется в заголовочный файл, который включается везде, где требуется добавить новый тип идентификатора:

//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();

Для моего приложения я хотел, чтобы несколько абстрактных базовых классов имели связанный с ними тип идентификатора. Поэтому для каждого экземпляра шаблона 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 
*/

Надеюсь, это поможет! Пожалуйста, дайте мне знать о любых проблемах.

1 голос
/ 31 января 2010

C ++ уже встроен.

Вы можете использовать оператор typeid для возврата класса type_info. type_info:name() вернет (уникальное) имя класса.

1 голос
/ 31 января 2010

Во-первых, почему? В любом случае вы можете легко установить идентификаторы вручную:

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);

Конечно, вам придется вручную отслеживать идентификаторы для каждого класса; в этот момент я задам оригинальный вопрос: почему?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...