Ok, the context is some serialization / deserialization code that will parse a byte stream into an object representation that s easier to work with (and vice-versa).
Here s a simplified example with a base message class and then depending on a type header, some more data/function are present and we must choose the right subclass to instantiate:
class BaseMessage {
public:
enum Type {
MyMessageA = 0x5a,
MyMessageB = 0xa5,
};
BaseMessage(Type type) : mType(type) { }
virtual ~BaseMessage() { }
Type type() const { return mType; }
protected:
Type mType;
virtual void parse(void *data, size_t len);
};
class MyMessageA {
public:
MyMessageA() : BaseMessage(MyMessageA) { }
/* message A specific stuf ... */
protected:
virtual void parse(void *data, size_t len);
};
class MyMessageB {
public:
MyMessageB() : BaseMessage(MyMessageB) { }
/* message B specific stuf ... */
protected:
virtual void parse(void *data, size_t len);
};
In a real examples, there would be hundreds of different message types and possibly several level or hierarchy because some messages share fields/functions with each other.
Now, to parse a byte string, I m doing something like:
BaseMessage *msg = NULL;
Type type = (Type)data[0];
switch (type) {
case MyMessageA:
msg = new MyMessageA();
break;
case MyMessageB:
msg = new MyMessageB();
break;
default:
/* protocol error */
}
if (msg)
msg->parse(data, len);
But I don t find this huge switch very elegant, and I have the information about which message has which type value twice (once in the constructor, one in this switch) It s also quite long ...
I m looking for a better way that would just be better ... How to improve this?