Issues with dynamic_cast from parent to child - c++

I'm working on a basic client server application in C++ using sockets that will run a game of battleship. All communication between client and server is in the form of a simple object hierarchy that looks something like this:
namespace Message {
enum MessageType { BASE, RESULT };
class BattleshipMessage {
public:
virtual MessageType get_type() { return BASE; }
virtual ~BattleshipMessage() {}
};
class ResultMessage : public BattleshipMessage {
public:
char _attackResult;
ResultMessage( char result ) : _attackResult( result ) {}
virtual MessageType get_type() { return RESULT; }
~ResultMessage() {}
};
}
When receiving an object sent through the socket, I would like to be able to receive it as a generic BattleshipMessage and then based on the MessageType returned by get_type() cast it to the appropriate child class to retrieve whatever additional information I might need to process the message. I'm afraid that C# has made me soft as I've done this sort of thing with easy syntax like ResultMessage result = message as ResultMessage however I'm stuck trying to get my C++ implementation working.
BattleshipMessage* message;
recv( hAccepted, reinterpret_cast<char*>( &message ), sizeof(message), 0 );
switch ( message->get_type() ) {
case RESULT:
if ( ResultMessage* result = dynamic_cast<ResultMessage*>(message)) {
std::string celebration = "HOORAY!";
}
break;
}
I get Access violation reading location when I dereference the pointer and try to call get_type(). Can anyone point me in the right direction?

sizeof(message)
gives the size of the pointer, which is typically 32-bit or 64-bit depending on your machine. You want
sizeof(BattleshipMessage)
which gives the size of the class. Even then, I'm not sure this is the right approach since each class object will contain a pointer to the vtable which handles the dynamic dispatch/virtual function calls, and sending the class across machines using the raw casting approach that you use will invalidate that pointer.
I think you should first serialize your object (i.e. convert it to a stream of characters) before sending it across the network, then deserialize to reconstruct the class:
Is it possible to serialize and deserialize a class in C++?

Get rid of all the virtual methods, and store MessageType as a member variable in BattleshipMethod. Then your code should work.

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.

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

Multi-site execution : Getting rid of virtual table with inheritance (legacy code)

I've been stuck for some time on this problem, and I need your help.
My C++ application is running on multiple exec sites. My problem is that I cannot pass objects holding a virtual table, because sites do not share memory (thus a virtual method from a given object will lead to an undefined behaviour). By "I cannot pass" I mean : I do not want any virtual table.
The fun thing is there's not only inheritance, but also templates and eerie conception...
Here is the code
// "Main" code
List< Animals, 5 > list;
List< Animals, 8 > list2;
list.concatenate( list2 );
// GenericList.hpp
template< Type >
class GenericList
{
virtual getBuffer(void) = 0;
virtual getSize(void) = 0;
void concatenate( GenericList<Type> gList)
{
int size = gList.getSize(); // Call to the child...
...getBuffer()...
// processing, etc.
}
}
// List.hpp
template< Type, Size_ >
class List : public GenericList< Type >
{
int getSize()
{
return Size_;
}
Type * getBuffer()
{
return buffer;
}
Type buffer[Size_];
}
How can I get rid of inheritance ?
EDIT/ In light of the first few answers, I can tell you that I cannot implement a better serialization, the code being private.
If you just want to get rid of virtual tables, you don't have to get rid of inheritance. You have to get rid of virtual functions. Looking at the code you post, maybe you can make a few changes so that getSize and getBuffer are in GenericList, so you can make them non-virtual, but that really depends on the rest of your code.
The first question is, however, why would you worry about virtual tables in the first place? When you serialize the objects, you should serialize their data in order to preserve their state, and the state is the only thing you should pass around.
I think you are blaming the wrong part of the problem there... if you have a distributed system, you have to make sure that the serialized data that is sent on the wire contains enough information to rebuild the state of the object on the other end of the connection.
I believe that the problem you are facing is that you are sending raw data over the wire, while you should have a serialization mechanism that is able to encode the actual type of the object being sent and rebuild the object on the opposite end with the exact same type. In the case of an object belonging to a class with virtual functions, that will mean that the two objects are not equal bitwise, as on each end of the connection the pointer to the vtable will refer to a different location in memory, but they will be semantically equal, which is what you need to be able to process the objects on the other end.

C++ design - Network packets and serialization

I have, for my game, a Packet class, which represents network packet and consists basically of an array of data, and some pure virtual functions
I would then like to have classes deriving from Packet, for example: StatePacket, PauseRequestPacket, etc. Each one of these sub-classes would implement the virtual functions, Handle(), which would be called by the networking engine when one of these packets is received so that it can do it's job, several get/set functions which would read and set fields in the array of data.
So I have two problems:
The (abstract) Packet class would need to be copyable and assignable, but without slicing, keeping all the fields of the derived class. It may even be possible that the derived class will have no extra fields, only function, which would work with the array on the base class. How can I achieve that?
When serializing, I would give each sub-class an unique numeric ID, and then write it to the stream before the sub-class' own serialization. But for unserialization, how would I map the read ID to the appropriate sub-class to instanciate it?
If anyone want's any clarifications, just ask.
-- Thank you
Edit: I'm not quite happy with it, but that's what I managed:
Packet.h: http://pastebin.com/f512e52f1
Packet.cpp: http://pastebin.com/f5d535d19
PacketFactory.h: http://pastebin.com/f29b7d637
PacketFactory.cpp: http://pastebin.com/f689edd9b
PacketAcknowledge.h: http://pastebin.com/f50f13d6f
PacketAcknowledge.cpp: http://pastebin.com/f62d34eef
If someone has the time to look at it and suggest any improvements, I'd be thankful.
Yes, I'm aware of the factory pattern, but how would I code it to construct each class? A giant switch statement? That would also duplicade the ID for each class (once in the factory and one in the serializator), which I'd like to avoid.
For copying you need to write a clone function, since a constructor cannot be virtual:
virtual Packet * clone() const = 0;
Which each Packet implementation implement like this:
virtual Packet * clone() const {
return new StatePacket(*this);
}
for example for StatePacket. Packet classes should be immutable. Once a packet is received, its data can either be copied out, or thrown away. So a assignment operator is not required. Make the assignment operator private and don't define it, which will effectively forbid assigning packages.
For de-serialization, you use the factory pattern: create a class which creates the right message type given the message id. For this, you can either use a switch statement over the known message IDs, or a map like this:
struct MessageFactory {
std::map<Packet::IdType, Packet (*)()> map;
MessageFactory() {
map[StatePacket::Id] = &StatePacket::createInstance;
// ... all other
}
Packet * createInstance(Packet::IdType id) {
return map[id]();
}
} globalMessageFactory;
Indeed, you should add check like whether the id is really known and such stuff. That's only the rough idea.
You need to look up the Factory Pattern.
The factory looks at the incomming data and created an object of the correct class for you.
To have a Factory class that does not know about all the types ahead of time you need to provide a singleton where each class registers itself. I always get the syntax for defining static members of a template class wrong, so do not just cut&paste this:
class Packet { ... };
typedef Packet* (*packet_creator)();
class Factory {
public:
bool add_type(int id, packet_creator) {
map_[id] = packet_creator; return true;
}
};
template<typename T>
class register_with_factory {
public:
static Packet * create() { return new T; }
static bool registered;
};
template<typename T>
bool register_with_factory<T>::registered = Factory::add_type(T::id(), create);
class MyPacket : private register_with_factory<MyPacket>, public Packet {
//... your stuff here...
static int id() { return /* some number that you decide */; }
};
Why do we, myself included, always make such simple problems so complicated?
Perhaps I'm off base here. But I have to wonder: Is this really the best design for your needs?
By and large, function-only inheritance can be better achieved through function/method pointers, or aggregation/delegation and the passing around of data objects, than through polymorphism.
Polymorphism is a very powerful and useful tool. But it's only one of many tools available to us.
It looks like each subclass of Packet will need its own Marshalling and Unmarshalling code. Perhaps inheriting Packet's Marshalling/Unmarshalling code? Perhaps extending it? All on top of handle() and whatever else is required.
That's a lot of code.
While substantially more kludgey, it might be shorter & faster to implement Packet's data as a struct/union attribute of the Packet class.
Marshalling and Unmarshalling would then be centralized.
Depending on your architecture, it could be as simple as write(&data). Assuming there are no big/little-endian issues between your client/server systems, and no padding issues. (E.g. sizeof(data) is the same on both systems.)
Write(&data)/read(&data) is a bug-prone technique. But it's often a very fast way to write the first draft. Later on, when time permits, you can replace it with individual per-attribute type-based Marshalling/Unmarshalling code.
Also: I've taken to storing data that's being sent/received as a struct. You can bitwise copy a struct with operator=(), which at times has been VERY helpful! Though perhaps not so much in this case.
Ultimately, you are going to have a switch statement somewhere on that subclass-id type. The factory technique (which is quite powerful and useful in its own right) does this switch for you, looking up the necessary clone() or copy() method/object.
OR you could do it yourself in Packet. You could just use something as simple as:
( getHandlerPointer( id ) ) ( this )
Another advantage to an approach this kludgey (function pointers), aside from the rapid development time, is that you don't need to constantly allocate and delete a new object for each packet. You can re-use a single packet object over and over again. Or a vector of packets if you wanted to queue them. (Mind you, I'd clear the Packet object before invoking read() again! Just to be safe...)
Depending on your game's network traffic density, allocation/deallocation could get expensive. Then again, premature optimization is the root of all evil. And you could always just roll your own new/delete operators. (Yet more coding overhead...)
What you lose (with function pointers) is the clean segregation of each packet type. Specifically the ability to add new packet types without altering pre-existing code/files.
Example code:
class Packet
{
public:
enum PACKET_TYPES
{
STATE_PACKET = 0,
PAUSE_REQUEST_PACKET,
MAXIMUM_PACKET_TYPES,
FIRST_PACKET_TYPE = STATE_PACKET
};
typedef bool ( * HandlerType ) ( const Packet & );
protected:
/* Note: Initialize handlers to NULL when declared! */
static HandlerType handlers [ MAXIMUM_PACKET_TYPES ];
static HandlerType getHandler( int thePacketType )
{ // My own assert macro...
UASSERT( thePacketType, >=, FIRST_PACKET_TYPE );
UASSERT( thePacketType, <, MAXIMUM_PACKET_TYPES );
UASSERT( handlers [ thePacketType ], !=, HandlerType(NULL) );
return handlers [ thePacketType ];
}
protected:
struct Data
{
// Common data to all packets.
int number;
int type;
union
{
struct
{
int foo;
} statePacket;
struct
{
int bar;
} pauseRequestPacket;
} u;
} data;
public:
//...
bool readFromSocket() { /*read(&data); */ } // Unmarshal
bool writeToSocket() { /*write(&data);*/ } // Marshal
bool handle() { return ( getHandler( data.type ) ) ( * this ); }
}; /* class Packet */
PS: You might dig around with google and grab down cdecl/c++decl. They are very useful programs. Especially when playing around with function pointers.
E.g.:
c++decl> declare foo as function(int) returning pointer to function returning void
void (*foo(int ))()
c++decl> explain void (* getHandler( int ))( const int & );
declare getHandler as function (int) returning pointer to function (reference to const int) returning void