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

发布于 2024-08-20 06:27:30 字数 354 浏览 8 评论 0原文

我有很多 C++ 课程。

我希望每个类都具有以下内容:

static int unique_id;

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

最简单的方法似乎是通过类线程化单例。

但是,我不知道静态类成员/在 main 之前发生的事情何时被调用。

(1) 如果你有一个不涉及使用单例的解决方案,那也很好

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

int unique_id(); 

那也很好。

谢谢!

I have a bunch of C++ classes.

I want each class to have something like:

static int unique_id;

All instances of a same class should have the same unique_id; different classes should have different unique_id's.

The simplest way to do this appears to be threading a singleton through the classes.

However, I don't know what's called when for static class members / things that happen before main.

(1) if you have a solution that does not involve using singleton, that's fine too

(2) if you have a solution that gives me a :

int unique_id(); 

that is fine too.

Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

蘑菇王子 2024-08-27 06:27:30

拥有一个在每次创建时递增其 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();
    }
};

Have a class that increments it's ID on each creation. Then use that class as a static field in each object that is supposed to have an 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();
    }
};
酒与心事 2024-08-27 06:27:30

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

Building on 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();

Use it like this:

class my_class : public id_base<my_class> {
  // ...
};
苦妄 2024-08-27 06:27:30

实际上这与 RTTI 非常相似。为了实现 (2),可以利用 C++ 的内置 RTTI。对*this调用typeid,并将typeinfo的地址作为唯一ID。

缺点:a)ID 不固定(重新编译会改变它们),b)信息仅在给定类实例的情况下可用,c)它很难看。

你为什么想要这个?

Actually that's very similar to RTTI. To achieve (2), C++'s buildin RTTI can be exploited. Call typeid on *this, and take the address of the typeinfo as unique ID.

Conss: a) IDs aren't be fixed (recompile would change them), and b) the information is only available given an instance of the class, c) it's ugly.

Why do you want this?

怪我鬧 2024-08-27 06:27:30

C++ 已内置此功能。

您可以使用 typeid 运算符返回 type_info 类。 type_info:name() 将返回类的(唯一)名称。

C++ has this already built in.

You can use the typeid operator to return a type_info class. The type_info:name() will return the (unique) name of the class.

李白 2024-08-27 06:27:30

首先,为什么?无论如何,您都可以轻松地手动设置 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;此时,我会问原来的问题:为什么?

First, why? In any case, you can manually set the IDs easily:

template <int id>
struct base { enum { unique_id = id }; };

class foo: public base<5> { ... };
class bar: public base<10> { ... };

Then

foo x;
bar y;
assert(x.unique_id == 5);
assert(y.unique_id == 10);

Of course, you'll have to manually keep track of the IDs for each class; at this point, I'll ask the original question: why?

金兰素衣 2024-08-27 06:27:30

我最近发现了 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 
*/

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

I have recently found sbi's version of Kornel's solution to be very useful. Thank you both for providing your answers. However, I wanted to extend the solution further so that several types of IDs can be easily created without creating a separate pair of id_impl and id_base classes for each new type.

To do this I templated the id_impl class, and added another argument to the id_base. The result is encapsulated in a header file that is included anywhere one wants to add a new ID type:

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

For my application I wanted several abstract base classes to have an ID type associated with them. So for each instance of the GeneralIDbase template the types specified are: the abstract base class of the derived class being declared, and the derived class being declared.

The following main.cpp is an example:

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

The output of this code is

/*
objA1.GetID() = 1 
objA2.GetID() = 2 
objB1.GetID() = 1 
objB2.GetID() = 2 
*/

I hope this helps! Please let me know of any issues.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文