Question

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

Was it helpful?

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.
  }
}

OTHER TIPS

If you want the messages to return the data, but for example MsgType1 should make it all lower case, and MsgTyp2 all upper case you could make a virtual function in MsgBase called, for example,

virtual char *getData();

and this function should be reimplemented in child classes so that it does with the data what you want it to do. This way when you call this function on base class pointer, you will get reimplemented functionality, depending to what type the actual pointer is, at the moment of calling.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top