将ID号映射到类

Mapping an ID number to a class

本文关键字:映射 ID      更新时间:2023-10-16

我正在设置一个系统,在这个系统中,我可以根据从文件中读取的一些信息动态地实例化类。这必须在运行时完成。所讨论的类是多态的,并且都继承自CBaseTheoryEnt类。我想做的是将ID号与每个类关联起来(例如,与无序映射关联)。实际上,我的管理类将查看从输入文件中读取的一系列ID号,然后实例化相应的类。将类与ID关联,然后根据输入实例化它们的理想且有效的方法是什么?

这样做的一种方法是使用模板函数实例化CBaseTheoryEnt的子类:

template<typename T>
CBaseTheoryEnt* instantiator() {
    return new T;
}

然后为每个从CBaseTheoryEnt派生的类设置一个hash_map或这些函数的数组,并将该类的键与该类的实例化器相关联。当对数组或映射进行索引时,将得到一个函数,当调用该函数时,该函数将返回一个指向相应类实例的指针。

例如,如果你有类A, B和C,并且A的id为0,B为1,C为2,那么你有:

typedef CBaseTheoryEnt* (*instantiator_ptr)();
instantiator_ptr classes[] = {
    &instantiator<A>,
    &instantiator<B>,
    &instantiator<C>
};

然后像

一样使用
int idx = get_class_id();
CBaseTheoryEnt* inst = classes[idx]();

你没有给出太多的细节,所以这里有一个相当通用的方法,使用map可能适用:

struct Base
{
  virtual int ID() const = 0;
  // ...
};
typedef Base * (*create_fp)();
typedef std::map<int, create_fp> create_map;
class DerivedA : public Base { /* ... */ };
class DerivedB : public Base { /* ... */ };
class DerivedC : public Base { /* ... */ };
namespace BaseCreators
{
  DerivedA * makeA() { /* ... */ }
  DerivedB * makeA() { /* ... */ }
  DerivedC * makeA() { /* ... */ }
}
const create_map creators {
  { 1, BaseCreators::makeA },
  { 2, BaseCreators::makeB },
  { 3, BaseCreators::makeC }
};
int main()
{
  int a = get_id_from_user();
  create_fp cr = creators.find(a)->second; // or check for existence first
  Base * b = cr();
}

(如果您没有c++ 11,您将不得不使creators映射为非常量并手动填充它)