为类类型 C++ 创建唯一 ID

Posted

技术标签:

【中文标题】为类类型 C++ 创建唯一 ID【英文标题】:Creating a unique ID for class types C++ 【发布时间】:2016-10-18 02:33:55 【问题描述】:

我的目标是为特定班级的每个孩子创建一个唯一的 ID(以 0 开头)。我不确定这是否可能以我想要的方式,但我想我会在这里问作为最后的手段。

一些上下文:

我正在创建自己的 2D 游戏引擎,并且我希望它有一个 ECS,因为它是骨干(在任何人说什么之前,我这样做是一种学习经验,我知道我可以使用已经存在的游戏引擎)。我的想法是每个实现“EntityComponent”类的类都应该有一个唯一的 ID。这需要针对每个孩子,而不是针对每个对象。我想使用此 ID 作为数组的索引来查找实体的组件。每个组件获得的实际 ID 并不重要,每个组件不需要在每次运行时都分配 ID。

我希望有某种方法可以为每个类创建类似于静态变量的东西(实现实体组件类)。需要快速获取此值,因此进行 unordered_map 查找比我想要的要慢。我不想做的一件事是自己为每个组件设置 ID。一旦制造了许多组件,这可能会导致问题,如果我忘记设置它或将两个组件设置为相同的 ID,则可能会导致问题。

我的一个想法是在 EntityComponent 中创建一个名为 ID 的变量(以及获取它的 getter)。构建实体时,它会查找无序映射(在运行时生成,为每个类分配一个 ID)以获取它应该具有的 ID。在施工时查看一次的价格很好。我看到的唯一问题是有很多冗余数据(尽管总的来说它似乎只占很小的一部分)。有了这个,每个单独的转换组件都必须存储它的 ID 是 x。这意味着可能有成千上万个转换组件正在存储这个 ID 值,而真正需要的只有 1 个。

基本上,我正在寻找一种非常快速的方法来查找类 TYPE 的 ID。这可以通过查找来实现,但需要快速查找。如果可能的话,我想要比 unordered_map 更快的东西。如果这可以通过编译时技巧(也许是枚举?)甚至是模板来完成,我很想听听你的想法。我知道过早的优化是不好的,但是能够快速获得一个组件是一件大事。

我要问的很可能是不可能的。只是想我会先在这里问一下。我还应该注意我试图避免在子类中实现这一点。我不想为每个子类设置相同的代码来创建一个 id。

谢谢。

【问题讨论】:

【参考方案1】:

为了获得与对象的实际类型相对应的东西,它要么需要在对象本身中,要么通过虚函数访问。否则类型将由与之关联的变量的类型决定。

当速度和大小都很重要时,一个常见的选项是为每种类型关联一个整数标识符(当在编译时知道完整的类型列表时),并在您想要做某事时以特定方式使用该整数值基于类型。

整数机制通常使用enum 为每种类型生成相应的值,并在每个对象中都有该字段。

虚拟方法的多样性,我在每个类中使用了 boost::uuid 和一个静态数据成员,并为它使用了一个虚拟方法 get'er。

【讨论】:

哎呀不是按回车的意思。我要问你的整数标识符评论。你有任何链接到一个例子,看看我是否可以使用它?我的目标是不需要额外的步骤来创建 EntityComponent。我想创建一个继承自它的新类,其他一切都会自动发生。如果有办法在编译时创建枚举,我认为那将是完美的。 @Lolop 不幸的是,我知道的例子非常复杂(而且我并不完全理解它们)——clang 和 v8 都使用这个系统作为伪 RTTI 系统,但是有多个级别的宏来组织一切。更简单的版本是只有一个枚举 ClassId CLASS_ONE, CLASS_TWO, CLASS_THREE 并有一个 ClassId class_id = CLASS_;在您的每个课程中。 不幸的是,我打算做一些类似于 Unity 的事情,并将 C# 作为我的游戏的脚本语言(我想学习 C++/CLI)。我认为这意味着不可能使用定义,因为我不想每次制作新的 C# 组件时都必须修改游戏引擎(想法是让它们分开)。 unity 不使用 c# 作为脚本语言——它使用 C# 作为唯一的语言。至少据我了解。 我认为在我原来的帖子中写的想法现在还可以。这篇文章只是为了看看是否有更好的东西。当然它有冗余数据,但每个组件只会额外增加 16 位(1 位短)。如果我有数十万个组件,它可能会增加几兆字节,但总的来说我认为它可以忽略不计。我更喜欢速度而不是内存。【参考方案2】:

EntityComponent 中声明一个虚函数newId()。 实现此函数以获取和递增每个类中的静态变量,您希望哪些子级具有唯一的 Id。 在构造函数中分配 Id: mId = newId();

【讨论】:

这需要我在每个子类中创建一个静态变量,对吧?所以 Transform 需要它自己的静态“mID”变量,而且我还必须为健康组件创建一个静态“mID”变量?如果可以的话,我想避免这种情况。我想让所有这些 ID 内容远离子类,并让它们被分配一个值,而不是让它们获得自己的值。这可能是不可能的,但我想我会问以防万一 现在我明白了。不是子类的每个对象都有唯一的 Id,而是每个子类。您对运营商typeid不满意吗?例如,您可以获取一个类名,并将其用作 Id。 我可以强制 TypeID 从 0 开始并以 1 开始吗?我将它用于数组索引,所以我需要它是 1 - x 增量值。对于我想要的东西来说,查找有点太慢了,所以任何类型的地图都不适合我。【参考方案3】:

不知道这是否是您的意思,我知道这是一篇旧帖子,但这就是我目前处理类似问题的方式,也许它会对其他人有所帮助。 (我也这样做作为 uni 的学习经验 :))

在控制类或它自己的实用程序类中:

enum class EntityType TYPE_ONE = 0, TYPE_TWO =1;

在类头中:

#include "EntityType.h"
class Whatever
public:

  inline void getType()return _type;
OR
  inline void getType()return EntityType::TYPE_ONE;

private:
  EntityType _type = EntityType::TYPE_ONE;

;

希望这对任何人都有帮助:)

【讨论】:

以上是关于为类类型 C++ 创建唯一 ID的主要内容,如果未能解决你的问题,请参考以下文章

c++ template 判断是否为类类型

使用 c++11 创建唯一类型 ID

如何将模板定义转换为类

C++ 为类模板提供初始化列表构造函数

C++类型转换函数

C++ 模板详解(转)