Domanda

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?

È stato utile?

Soluzione

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++?

Altri suggerimenti

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

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top