Dynamically register constructor methods in an AbstractFactory at compile time using C++ templates

后端 未结 7 2030
予麋鹿
予麋鹿 2020-12-02 19:19

When implementing a MessageFactory class to instatiate Message objects I used something like:

class MessageFactory 
{
  public:
    static Message *create(in         


        
7条回答
  •  半阙折子戏
    2020-12-02 20:21

    This is a modified version that uses a MessageFactory singleton and a std::map to store constructors. It works great so far but comments are welcome.

    I am still trying to find a way to avoid creating constructors for each message class. I know is possible because the original library can do it. Unfortunately I only have the header files so no idea on the implementation details.

    #include 
    #include 
    #include 
    #include 
    #include 
    
    class Message
    {
       protected:
          Message() {};
    
       public:
          virtual ~Message() { }
          int getMessageType() const { return m_type; }
          virtual void say() = 0;
    
       protected:
          uint16_t m_type;
    };
    
    template
    class MessageTmpl: public Message
    {
       enum { _MESSAGE_ID = TYPE };
       public:
         static Message* Create() { return new IMPL(); }
         static const uint16_t MESSAGE_ID; // for registration
         static void Enable() { volatile uint16_t x = MESSAGE_ID; }
       protected:
          MessageTmpl() { m_type = MESSAGE_ID; } //use parameter to instanciate template
    };
    
    class MessageFactory 
    {
       public:
         typedef Message* (*t_pfFactory)();
    
         static MessageFactory *getInstance()
         {
           static MessageFactory fact;
           return &fact;
         }
    
         uint16_t Register(uint16_t msgid, t_pfFactory factoryMethod)
         {
           printf("Registering constructor for msg id %d\n", msgid);
           m_List[msgid] = factoryMethod;
           return msgid;
         }
    
         Message *Create(uint16_t msgid)
         {
           return m_List[msgid]();
         }
    
         std::map m_List;
    
      private:
         MessageFactory() {};
         MessageFactory(MessageFactory const&) {};
         MessageFactory& operator=(MessageFactory const&);
         ~MessageFactory() {};
    };
    
    //std::map MessageFactory::m_List;
    
    template 
    const uint16_t MessageTmpl::MESSAGE_ID = MessageFactory::getInstance()->Register(
         MessageTmpl::_MESSAGE_ID, &MessageTmpl::Create);
    
    
    class PingMessage: public MessageTmpl < 10, PingMessage >
    { 
      public:
      PingMessage() {}
      virtual void say() { printf("Ping\n"); }
    };
    
    class PongMessage: public MessageTmpl < 11, PongMessage >
    { 
      public:
      PongMessage() {}
      virtual void say() { printf("Pong\n"); }
    };
    
    int main(int argc, char **argv)
    {
      Message *msg1;
      Message *msg2;
    
      msg1 = MessageFactory::getInstance()->Create(10);
      msg1->say();
    
      msg2 = MessageFactory::getInstance()->Create(11);
      msg2->say();
    
      delete msg1;
      delete msg2;
    
      return 0;
    }
    

提交回复
热议问题