Search code examples
c++radixderived

Best way to change from base class to derived class


I know this is asked in various ways on this forum, but I still can't quite figure out the best way to go about what I need to do (after reading various other posts). So I have decided to seek further advice!

I have a message class hierarchy, something like (omitted most details):

class MsgBase
{
    public:
        uint8_t getMsgType(void);

    protected: // So that derived classes can access the member
        char _theMsgData[100];
}

class MsgType1 : public MsgBase
{
}

class MsgType2 : public MsgBase
{
}

So what happens is I received a block of message data and I use it to create my message. But I don't know which message to create until I read out the message type. So I end up with:

MsgBase rxMsg(rxData);
if (rxMsg.getMsgType() == 1)
{
    // Then make it a MsgType1 type message
}
else if (rxMsg.getMsgType() == 2)
{
    // Then make it a MsgType2 type message
}

This is the bit I am stuck on. From what I have read, I cannot dynamical cast from base to derived. So my current option is to instantiate a whole new derived type (which seems inefficient), i.e.:

if (rxMsg.getMsgType() == 1)
{
    // Now use the same data to make a MsgType1 message.
    MsgType1 rxMsg(rxData);
}

Is there a way that I can look at the data as the base class so that I can determine its type and then "molymorph" it into the required derived type?

Thanks, Fodder


Solution

  • What is rxData? I assume it's just a blob of data, and you should parse it to determine the message type before you create any message object. And depending on if the message data has always the same length you should consider using std::array or std::vector to pass the data blob around.

    typedef std::vector<char> MsgDataBlob;
    
    class MsgBase
    {
        public:
            uint8_t getMsgType();
            MsgBase(MsgDataBlob blob) : _theMsgData(std::move(blob)) {}
    
        protected: // So that derived classes can access the member
            MsgDataBlob _theMsgData;
    };
    
    //derived classes here...
    
    //this could be either a free function or a static member function of MsgBase:
    uint8_t getMessageType(MsgDataBlob const& blob) { 
      // read out the type from blob
    }
    
    std::unique_ptr<MsgBase> createMessage(MsgDataBlob blob) {
      uint8_t msgType = getMessageType(blob);
      switch(msgType) {
        case 1: return make_unique<MsgDerived1>(std::move(blob));
        case 2: return make_unique<MsgDerived2>(std::move(blob));
        //etc.
      }
    }