代码之家  ›  专栏  ›  技术社区  ›  stefanB

通过模板将字符ID映射到C++中的类名?

c++
  •  1
  • stefanB  · 技术社区  · 16 年前

    Is there a way to instantiate objects from a string holding their class name?


    C++中有一种(更好的)将字符串ID映射到类名的方法。我怀疑可能有一种通过模板的方法,但我无法找到正确的方法。

    例如,如果我有多条消息,每条消息在第一个字节中存储一个字符id。因此消息A12345将实例化类a(),消息B12345将映射到类B()。

    我有一组消息解析器,其中每个类都可以解析给定的消息。问题是我必须手动生成解析给定消息的类(例如class A())和消息id(例如“A”)之间的映射。

    这就是我现在在代码中所做的,我在想,是否有一个消除C++中的切换的好方法(模板魔术?)

    Msg * msg;
    switch(data[0])
    {
        case 'A': msg = new A(); break;
        case 'B': msg = new B(); break;
        ...
    }
    
    msg->parse(data);
    

    在旁注中,大多数情况下id实际上是2个字符长的,因此“A1”“B1”等等。我使用相同的类名来跟踪类,例如“A1”可以由类A1()解析,等等。

    笔记 C++: Is there a way to instantiate objects from a string holdig their class name? 所以我建议结束这个问题。

    5 回复  |  直到 8 年前
        1
  •  2
  •   rlbond    16 年前

    Boost.Any . 然后,您可以将您的any解释为A或B:

    if (myAny.type() == typeid(A))
    {
        boost::any_cast<A>(myAny).whatever();
    }
    else if (myAny.type() == typeid(B))
    {
        // do whatever
    }
    
        2
  •  1
  •   dirkgently    16 年前

    你不能消除 switch (将会是 if-else 如果它们是字符串)。快捷方式是使用宏:

    #define str(x) #x
    #define xstr(x) str(x)
    #define cond(var, type) (var == xstr(type)) { new type; }  
    

    并将其用作:

    if cond(data, A)
    else if cond(data, B)
    
        3
  •  1
  •   Community CDub    8 年前

    正如其他人所说,不能使用模板(模板是在编译时计算的,但您的角色id是在运行时计算的)。

    Instantiate objects from a String holding their class name

    我建议你保持简单。如果一个普通的开关可以做到这一点,保持这种方式。如果您以后真的需要扩展它,您仍然可以引入一些字符ID的自动查找等等。

        4
  •  1
  •   Zifre    16 年前

    使用模板或任何东西都无法做到这一点;C++没有反射。RTTI可能会有所帮助,但您不能在运行时根据类的名称创建类的实例(就像您在.NET或Java反射中所做的那样)。

    但是,可以使用宏使这一点更简单。假设您不希望只使用单个字符的类名(如示例中所示),则不能使用 switch . 试着这样做:

    #define CREATE_MSG(t) if(strcmp(data,#t)==0) msg=new t()
    
    // I know CREATE_MSG is not a good name,
    //but I couldn't think of something better
    
    Msg *msg;
    
    CREATE_MSG(A);
    CREATE_MSG(B);
    CREATE_MSG(C);
    
    msg->parse(data);
    
        5
  •  0
  •   ChrisW    16 年前

    您可以有一个数据结构(例如字典或成对数组),将字符串ID映射到构造类的静态函数。比如:

    Msg* createA() { return new A(); }
    Msg* createB() { return new B(); }
    
    typedef Msg* (*Pfn_create)();
    
    typedef std::map<char,Pfn_create> MsgMap;
    MsgMap s_msgMap;
    
    void initialize()
    {
      s_msgMap.insert(MsgMap::pair('A',createA));
      s_msgMap.insert(MsgMap::pair('B',createB));
    }
    
    void dispatch(const Data& data)
    {
      MsgMap::iterator it = s_msgMap.find(data[0]);
      Pfn_create creator = it->second;
      Msg* msg = creator();
      msg->parse(data);
    }