Best way to change from base class to derived class - c++

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

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

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.

Related

Calling a derived class method from the parent class' same method

My problem goes as follow: I am writing an extensible communication protocol between a server and a client. The objects needed to be transferred are using the command design pattern.
Here is the class format:
class command {
public:
using id = uint8_t;
using buffer = std::vector<char>;
enum command_t: id {a_command, another_command};
command() = delete;
command(id id): id_(id) {}
static command* unserialize(buffer);
virtual buffer const serialize() const = 0;
virtual void execute() = 0;
protected:
/* Not possible, see further where I explain. Keeping it here for
my example */
virtual static command* do_unserialize(buffer::iterator, buffer::iterator) = 0;
id id_;
};
class a_command;
class another_command;
Every command will be a subclass of command. A command_t id will be associated with every command. In the example above, a_command and another_command would have a respective class too.
command::serialize is implemented in the derived classes. What it does is it writes all the needed informations of the class in a byte array and returns it. Of course, the same thing goes for the protected command::do_unserialize - it takes a byte array and converts it to a command of the right type. But here is the problem:
The first byte of the buffer will always be the command::id associated with the good subclass.
When the server/client will receive data, it will read the command ID and then it needs to be able to unserialize it to the right command type. This is why it will need to call the static function command::unserialize and not one of the subclasses' do_unserialize.
A quick and dirty fix would be a command::unserialize looking like this:
command* command::unserialize(buffer b) {
auto it{b.begin()};
command::id const id{*it++};
switch(static_cast<command::command_t>(id)) {
case command::command_t::a_command:
return a_command::do_unserialize(it, b.end());
case command::command_t::another_command:
return another_command::do_unserialize(it, b.end());
default:
throw std::invalid_argument("command::unserialize: unknown command ID");
}
}
*** Actually not even, you cannot have a virtual static member function. So I have no idea how it could be implemented.
Even if it worked, it is not really fun, because it implies having to duplicate a line of code
for every new command created.
EDIT: A working example would be to move do_unserialize to the subclass constructor and return a pointer to the newly created object.
class derived_command: public command {
public:
derived_command(buffer::iterator beg, buffer::iterator end) {
// do_unserialize logic
}
};
// unserialize
switch (id) {
case command::command_t::derived_class: return new derived_class(b.begin(), b.end());
}
// ...
My question thus goes like this: Is there a way to dynamically link new commands only from the command::id field? A way to deduce the subclass to use from its ID? Else, is my design flawed? Is there a better way to do what I'm trying to do?
Thank you!

generic message dispatching library?

Is there a standard way to get rid of the switch/case block in a read loop?
i.e.
enum msg_type
{
message_type_1,
//msg types
}
struct header
{
msg_type _msg_type;
uint64_t _length;
}
struct message1
{
header _header;
//fields
}
struct message2
{
header _header;
//fields
}
//socket read loop
void read(//blah)
{
//suppose we have full message here
char* buffer; //the buffer that holds data
header* h = (header*)buffer;
msg_type type = h->_msg_type;
switch(type)
{
case msg_type_1:
message1* msg1 = (message1*)buffer;
//Call handler function for this type
//rest
}
}
this means that I have to inherit from a handler container base class which is of the form:
class handler_container_base
{
public:
virtual void handle(message1* msg){}
virtual void handle(message2* msg){}
//etc
}
and pass an object of that type to where the message loop can see and ask him to call those back.
One problem is, even when I want to implement and register only one handler for a single type I have to inherit from this class.
Another is this just looks ugly.
I was wondering if there are existing libraries which handle this problem (should be free). Or is there no better way of doing this rather than like this?
Other approaches that avoid inheritance are:
For a closed set of types:
Use a variant:
variant<message1_t, message2_t> my_message;
With a visitor you can do the rest. I recommend boost.variant.
You can also use a boost::any, for an open set of types, and copy the messages around at runtime.At some point you will have to cast back to the original type, though.
Another solution goes along the lines of Poco.DynamicAny, which will try to convert, to the type on the left in an assignment, similar to a dynamic language. But you need to register converters yourself for your types.

cannot convert between nested templated types

I am trying to write a message handler whose Base classes are
1-Handler base class
2-Handler Factory that generates proper handler for a proper message type
3-and a base generic class for message
their code is like this:
#include <map>
#include<iostream>
//Base Handler
template<class MSG>
class Handler
{
MSG message;
public:
Handler(MSG message):message(message){
}
virtual void handle() = 0;
MSG getMessage()
{
return message;
}
};
//Base Handler Factory
template<class MSG>
class HandlerFactory {
public:
virtual Handler<MSG> * create(MSG & message) = 0;
};
//Base message
template<class T>
class Message
{
T messageType;
public:
T getMessageType()
{
return messageType;
}
void setMessageType(T messageType_)
{
messageType = messageType_;
}
};
//Then, based on the message type, I write subclass for every base class:
//my custom types
enum MessageType
{
ANNOUNCE,
KEY_SEND,
KEY_REQUEST
};
//my first custom message format
class MyMessage_1 : public Message<MessageType>
{
//...
};
//my first custom handler
class MyMessageHandler_1 : public Handler<MyMessage_1>
{
public:
MyMessageHandler_1(MyMessage_1 &message_): Handler<MyMessage_1>(message_)
{
}
void handle(){}
};
//my custom handler factory
class MyHandlerFactory : public HandlerFactory<Message<MessageType> > {
Handler<Message<MessageType> > *value;
public:
MyHandlerFactory(){};
Handler<Message<MessageType> > * create(Message<MessageType> & message){
switch (message.getMessageType())
{
case ANNOUNCE:
MyMessage_1 t1;
value = new MyMessageHandler_1(t1);//error here
break;
//etc. etc.
default:
value = 0;
break;
};
return value;
};
};
//let's put a main so you can easily compile it
int main()
{
}
the problem is when, in switch-case clause, I try to create an instance of a handler for one of my custom message classes, I get the following error:
templateArgList.cpp: In member function ‘virtual Handler<Message<MessageType> >* MyHandlerFactory::create(Message<MessageType>&)’:
templateArgList.cpp:86:37: error: cannot convert ‘MyMessageHandler_1*’ to ‘Handler<Message<MessageType> >*’ in assignment
I was under the impression that:
Handler<Message<MessageType> > * can be casted as follows:
MyMessageHandler_1-> Handler<MyMessage_1>
^
|
`Message<MessageType>` which finally gives me:
`Handler<Message<MessageType> >` :P
Am I wrong? of course I am, why would I get the above error then :))
I just don't know why and how to fix it.
Therefore I will appreciate if you kindly help me with it.
thanks very much for your kind help
Here is a very simple program that is analogous to what you have done, but without the nested templates so that it's understandable:
#include <vector>
class A {
};
class B : public A {
};
int main() {
std::vector<A>* va;
va = new std::vector<B>;
}
And indeed, g++ gives the error:
error: cannot convert ‘std::vector<B>*’ to ‘std::vector<A>*’ in assignment
This should be clear -- a vector of A's is not the same as a vector of B's, even though B inherits from A. To be able to take advantage of inheritance, you have to have pointers to the objects that are related. For example:
int main() {
std::vector<A*> va(3);
for (int i=0; i<3; ++i) {
va[i] = new B;
}
}
The analogy here is:
std::vector< > ----> Handler< >
A ----> Message<MessageType>
B ----> MyMessage_1
By the way, did you realize that you define a variable named message in both MyMessageHandler_1 and also in Handler<>? This will cause MyMessageHandler_1::message to hide Handler<>::message. I'm not sure if this is what you want.
Also.. you might want to look into the Twisted package for Python, as it might be well suited to the application you're building. (If you don't mind using Python.)
Question: "any suggestion to alter my code?"
Response:
Well, I would try removing the templates and enjoying the power of inheritance. The Handler class can accept a Message object (or reference or pointer), as both of these are base classes. The HandlerFactory's create would also accept a Message object. Then you can proceed with the Message class having an enum MessageType type member variable and using switch inside HandlerFactor to determine the correct Handler-derived class to create.
Or instead of the enum, you could exploit inheritance even further by adding a "NewHandler()" function to Message, which would be pure virtual in Message and would be defined in the derived class. This way, you wouldn't need a switch -- each type of message knows what Handler it needs, and the factor simply calls message->NewHandler().
...It's a bit difficult to determine whether you need to use templates or not because I'm not sure where your project is headed. However, as a rough rule of thumb, it's a good idea to use templates when (a) you want to use equivalent blocks of code for different types and (b) you can't use inheritance to accomplish it. The std::vector<> is a good example -- the behavior of std::vector<int> and std::vector<float> is the same, but int's and float's aren't related by any common base, so rather than rewrite the code for a VectorI and VectorF, the compiler is asked to rewrite the code instead.
So far, it looks like you can exploit inheritance to do what you want. It has the added bonus of making it easier for other people to read your code, as well. :)

What's a good safe way to initialise memory for types I don't yet know about?

I started thinking about this after receiving an answer for this question. This is a bit tricky to explain, but I'll do my best.
I'm building a small(ish) 2D game engine. There are certain requirements that I need to satisfy, since this engine has to "work" with existing code that others have written for a different engine. Some change to existing code is inevitable, but I want to minimise it.
Users of my engine need to define entities called "gadgets". These are basically structs containing shapes and other state variables. These "gadgets" fall into classes, e.g. they may decide to define an icon gadget or a button gadget - or whatever.
They will also define a message handler for that class of gadgets.
E.g.
typedef struct
{
shape shapelist[5];
int num_options;
}interface;
static void interface_message_handler( interface * myself, message * msg )
{
switch( msg->type )
{
case NEW_MSG:
{
interface_descriptor * desc = msg->desc;
// initialize myself with contents of this message.
...
}
break;
....
}
}
Users have already given me the corresponding message handler function and also the number of bytes in a interface object. And they can then ask the engine to create new instances of their gadgets via IDs e.g:
engine->CreateNewGadget( interface_gadget_class_ID, welcome_interface_ID );
where interface_gadget_class_ID is the ID for that class of gadgets and welcome_interface_ID is the instance ID. At some point during CreateNewGadget I need to a) allocate memory to hold a new gadget and then call the gadget class's message handler on it, with a NEW_MSG so that it can initialize itself.
The problem is, if all I'm doing is allocating memory - that memory is uninitialized (and that means all the struct members are uninitialized - so if interface contains a vector, for example, then I'm going to get some wierd results if the message handler does anything with it ).
To avoid wierd results caused by doing stuff to unintialized memory, I really need to call a constructor for that memory as well before passing it to the gadget's message handler function.
e.g in the case of interface:
pfunc(new (memory) interface);
But my question is, if I have no knowledge of the types that users are creating, how can I do that?
// We create a typedef that refers to a function pointer
// which is a function that returns an interface pointer
typedef interface * (*GadgetFactory)(void);
// we'll actually create these functions by using this template function
// Different version of this function will produce different classes.
template<typename T>
interface * create_object()
{
return new T;
}
// This function takes care of setting everything up.
template<typename T>
void RegisterGadgetType(int gadget_type_id)
{
// Get outselves a copy of a pointer to the function that will make the object
GadgetFactory factory = create_object<T>;
// store factory somewhere
}
interface * CreateGadget(int gadget_type_id)
{
// get factory
GadgetFactory factory;
// factory will give me the actual object type I need.
return (*factory)();
}
RegisterGadgetType<S>(2);
CreateGadget(2);
as i see it, you always know because interface_gadget_class_ID defines the type to create.
you create a base c++ class: (corresponds to class interface in your example). this base class contains all of data members which are used by every interface subclass (that is, every gadget).
the base class also declares all methods common to every gadget. example: each gadget is able to receive a call handleMessage. handleMessage is pure virtual, because this method is the subclasses' role to fulfill.
then you extend/subclass to support the stuff you have to do with each gadget's specialization. at this point, you add the members and methods specific to each gadget subclass.
CreateNewGadget serves as a factory for all your subclasses, where the arguments determine which class you will create.
from there, c++ will handle construction/destruction, allocation sizes, etc..
if you're allowing plugins with their own factories in your engine, then you'll need another level, where third parties register their custom types and inherit from your base(s).
here's a simple layout of the interfaces (in non-compiled pseudo code):
namespace MONGadgets {
class t_interface {
protected:
t_interface(/* ... */);
public:
virtual ~t_interface();
/* each subclass must override handleMessage */
virtual t_result handleMessage(const t_message& message) = 0;
};
namespace InterfaceSubclasses {
class t_gadget1 : public t_interface {
public:
t_gadget1(const welcome_interface_ID& welcome);
virtual ~t_gadget1();
virtual t_result handleMessage(const t_message& message) {
std::cout << "t_gadget1\n";
}
/* gadget1 has no specific instance variables or methods to declare */
};
class t_gadget2 : public t_interface {
public:
t_gadget2(const welcome_interface_ID& welcome);
virtual ~t_gadget2();
virtual t_result handleMessage(const t_message& message) {
std::cout << "t_gadget2\n";
}
private:
/* here is an example of a method specific to gadget2: */
void drawShape(const unsigned& idx);
private:
/* here is gadget2's unique data: */
shape shapelist[5];
int num_options;
};
namespace ClassID {
enum { Gadget1 = 1, Gadget2 = 2 };
}
}
/* replaced by virtual t_result t_interface::handleMessage(const t_message&)
- static void interface_message_handler( interface * myself, message * msg );
*/
class t_gadget_factory {
public:
t_interface* CreateNewGadget(const interface_gadget_class_ID& classID, const welcome_interface_ID& welcome) {
switch (classID) {
case InterfaceSubclasses::ClassID::Gadget1 :
return new InterfaceSubclasses::gadget1(welcome);
case InterfaceSubclasses::ClassID::Gadget2 :
return new InterfaceSubclasses::gadget2(welcome);
/* ... */
}
}
};
}
Example code (ignoring my other suggestion, about factories and virtual functions):
typedef struct
{
shape shapelist[5];
int num_options;
} interface;
static void interface_message_handler( void * myself, message * msg )
{
switch( msg->type )
{
case NEW_MSG:
{
interface *self = new (myself) interface;
interface_descriptor * desc = msg->desc;
// initialize myself with contents of this message.
...
}
break;
case OTHER_MSG:
{
interface *self = static_cast<interface*>(myself);
...
}
break;
....
}
}
Then your CreateNewGadget code does:
void *ptr = malloc(some_amount);
msg newmsg;
newmsg.type = NEW_MSG;
// other fields
some_message_handler(ptr, &msg);
// now we have an initialized object, that we can add to our tree or whatever.
The less horrible version is more like this:
struct gadgetinterface {
virtual ~gadgetinterface() {}
virtual void handle_message(msg *) = 0;
};
struct mygadget : gadgetinterface {
void handle_message(msg *m) {
// no need for NEW_MSG, just do other messages
}
};
gadgetinterface *mygadget_factory(some parameters) {
// use some parameters, either passed to constructor or afterwards
return new mygadget();
}
Then we register a pointer to mygadget_factory with the gadget manager, and CreateNewGadget does this:
gadgetinterface *some_factory(some parameters); // that's it!
Where some_factory is the function pointer that was registered, so in the case of this gadget type, it points to mygadget_factory.

Design pattern to refactor switch statement

I have something like the following in the header
class MsgBase
{
public:
unsigned int getMsgType() const { return type_; }
...
private:
enum Types { MSG_DERIVED_1, MSG_DERIVED_2, ... MSG_DERIVED_N };
unsigned int type_;
...
};
class MsgDerived1 : public MsgBase { ... };
class MsgDerived2 : public MsgBase { ... };
...
class MsgDerivedN : public MsgBase { ... };
and is used as
MsgBase msgHeader;
// peeks into the input stream to grab the
// base class that has the derived message type
// non-destructively
inputStream.deserializePeek( msgHeader );
unsigned int msgType = msgHeader.getMsgType();
MsgDerived1 msgDerived1;
MsgDerived2 msgDerived2;
...
MsgDerivedN msgDerivedN;
switch( msgType )
{
case MSG_DERIVED_1:
// fills out msgDerived1 from the inputStream
// destructively
inputStream.deserialize( msgDerived1 );
/* do MsgDerived1 processing */
break;
case MSG_DERIVED_2:
inputStream.deserialize( msgDerived2 );
/* do MsgDerived1 processing */
break;
...
case MSG_DERIVED_N:
inputStream.deserialize( msgDerivedN );
/* do MsgDerived1 processing */
break;
}
This seems like the type of situation which would be fairly common and well suited to refactoring. What would be the best way to apply design patterns (or basic C++ language feature redesign) to refactor this code?
I have read that the Command pattern is commonly used to refactor switch statements but that seems only applicable when choosing between algorithms to do a task. Is this a place where the factory or abstract factory pattern is applicable (I am not very familiar with either)? Double dispatch?
I've tried to leave out as much inconsequential context as possible but if I missed something important just let me know and I'll edit to include it. Also, I could not find anything similar but if this is a duplicate just redirect me to the appropriate SO question.
You could use a Factory Method pattern that creates the correct implementation of the base class (derived class) based on the value you peek from the stream.
The switch isn't all bad. It's one way to implement the factory pattern. It's easily testable, it makes it easy to understand the entire range of available objects, and it's good for coverage testing.
Another technique is to build a mapping between your enum types and factories to make the specific objects from the data stream. This turns the compile-time switch into a run-time lookup. The mapping can be built at run-time, making it possible to add new types without recompiling everything.
// You'll have multiple Factories, all using this signature.
typedef MsgBase *(*Factory)(StreamType &);
// For example:
MsgBase *CreateDerived1(StreamType &inputStream) {
MsgDerived1 *ptr = new MsgDerived1;
inputStream.deserialize(ptr);
return ptr;
}
std::map<Types, Factory> knownTypes;
knownTypes[MSG_DERIVED_1] = CreateDerived1;
// Then, given the type, you can instantiate the correct object:
MsgBase *object = (*knownTypes[type])(inputStream);
...
delete object;
Pull Types and type_ out of MsgBase, they don't belong there.
If you want to get totally fancy, register all of your derived types with the factory along with the token (e.g. 'type') that the factory will use to know what to make. Then, the factory looks up that token on deserialize in its table, and creates the right message.
class DerivedMessage : public Message
{
public:
static Message* Create(Stream&);
bool Serialize(Stream&);
private:
static bool isRegistered;
};
// sure, turn this into a macro, use a singleton, whatever you like
bool DerivedMessage::isRegistered =
g_messageFactory.Register(Hash("DerivedMessage"), DerivedMessage::Create);
etc. The Create static method allocates a new DerivedMessage and deserializes it, the Serialize method writes the token (in this case, Hash("DerivedMessage")) and then serializes itself. One of them should probably test isRegistered so that it doesn't get dead stripped by the linker.
(Notably, this method doesn't require an enum or other "static list of everything that can ever exist". At this time I can't think of another method that doesn't require circular references to some degree.)
It's generally a bad idea for a base class to have knowledge about derived classes, so a redesign is definitely in order. A factory pattern is probably what you want here as you already noted.