Проблемы с dynamic_cast от родителя к ребенку

Я работаю над базовым клиент-серверным приложением на C ++, используя сокеты, которые будут запускать игру на линкоре. Все взаимодействие между клиентом и сервером происходит в форме простой иерархии объектов, которая выглядит примерно так:

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() {}
};
}

При получении объекта, отправляемого через сокет, я хотел бы иметь возможность получить его как универсальный BattleshipMessage, а затем на основе MessageType, возвращаемого get_type (), привести его к соответствующему дочернему классу, чтобы получить любую дополнительную информацию, которая может понадобиться для обработки сообщение. Я боюсь, что C # сделал меня мягким, так как я делал такие вещи с простым синтаксисом, как ResultMessage result = message as ResultMessage Однако я застрял, пытаясь заставить мою реализацию C ++ работать.

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

я получил Access violation reading location когда я разыменую указатель и пытаюсь вызвать get_type (). Может кто-то указать мне верное направление?

3

Решение

sizeof(message)

дает размер указателя, который обычно составляет 32-разрядный или 64-разрядный в зависимости от вашей машины. Ты хочешь

sizeof(BattleshipMessage)

который дает размер класса. Даже тогда, я не уверен, что это правильный подход, так как каждый объект класса будет содержать указатель на виртуальную таблицу, которая обрабатывает динамические диспетчерские / виртуальные вызовы функций, и отправка класса между компьютерами с использованием используемого метода прямого приведения приведет к аннулированию этот указатель.

Я думаю, что вы должны сначала сериализовать свой объект (т.е. преобразовать его в поток символов) перед отправкой его по сети, а затем десериализовать, чтобы восстановить класс:
Можно ли сериализовать и десериализовать класс в C ++?

3

Другие решения

Избавьтесь от всех виртуальных методов и сохраните MessageType как переменную-член в BattleshipMethod. Тогда ваш код должен работать.

0

По вопросам рекламы [email protected]