Полиморфное перечисление в C++

У меня есть эти Перечислимые объявления:

enum MessageType{  
    REQ_LOGIN,
    REQ_GET_FIELD,       

    RES_LOGIN,
    RES_GET_FIELD
}

enum Request{
    REQ_LOGIN,
    REQ_GET_FIELD
};

enum Respond{
    RES_LOGIN,
    RES_GET_FIELD
};

Очевидно, я повторяю элементы в Перечислении. Там какой-либо путь состоит в том, чтобы предотвратить это?

Править: Я использую "MessageType" на классе общего назначения для отправки его через сеть, с другой стороны я анализирую объект этого класса и диспетчеризирую сообщение. Но у меня есть различные клиенты; некоторые ожидают, что только объекты с "Запросом" вводят участника, и некоторые ожидают, что только объекты с "Ответом" вводят участника.

Используя класс "сообщения", я создаю "DispatcherRequest" s.

class Message
{
public:
……….
    MessageType messageType;
}


struct DispatcherRequest
{
..........
    Request type;
};
6
задан metdos 25 June 2010 в 12:21
поделиться

8 ответов

Почему бы не попробовать что-то подобное?

enum MainType{  
    REQUEST,
    RESPONSE
};

enum SubType{
    LOGIN,
    GET_FIELD
};

class Message {
   MainType type;
   SubType sub_type;
   ...
};
6
ответ дан 8 December 2019 в 17:18
поделиться

Трудно сказать, не зная идеи, лежащей в основе этого дизайна, но вы могли бы рассмотреть более объектно-ориентированный подход. Что-то вроде:

class Message {
    public:
        virtual void send() = 0;
};

class Request : public Message {
    public:
        virtual void send();
}

class Response : public Message {
    public:
        virtual void send();
}
4
ответ дан 8 December 2019 в 17:18
поделиться

Вы ссылаетесь на полиморфные перечисления, почему бы просто не использовать одно перечисление и назвать его так, как вы планировали назвать базовое перечисление, скажем «Тип сообщения»? Это убережет вас от повторения элементов.

2
ответ дан 8 December 2019 в 17:18
поделиться

Если мой комментарий к ответу PeterK ясен как грязь, вот полученный код:

class Message {
public:
    enum MainType {  
        REQUEST,
        RESPONSE
    };
    Message(MainType type_): type(type_) {}
    virtual void send() = 0;
private:
    MainType type;
};

class Request: public Message {
public:
    enum SubType {
        LOGIN,
        GET_FIELD
    };
    Request(SubType sub_type_): Message(Message::REQUEST), 
        sub_type(sub_type_) {}
    virtual void send();
private:
    SubType sub_type;
};

class Response: public Message {
public:
    enum SubType {
        LOGIN,
        GET_FIELD
    };
    Response(SubType sub_type_): Message(Message::RESPONSE), 
        sub_type(sub_type_) {}
    virtual void send();
private:
    SubType sub_type;
};
2
ответ дан 8 December 2019 в 17:18
поделиться

Шпион из java (извините за черновик):

class MessageType
{  
protected:
    MessageType(int value);//visible for descending classes only
    MessageType(const MessageType& other);
public:
    static const MessageType REQ_LOGIN, //assign later with integer value
    REQ_GET_FIELD,       

    RES_LOGIN,
   RES_GET_FIELD;
}

clas Request : public MessageType
{
};

clas Respond : public MessageType
{
};
0
ответ дан 8 December 2019 в 17:18
поделиться

В вашем примере кода значения из enum Request и enum Response имеют одинаковые значения (0 для REQ_LOGIN и RES_LOGIN и 1 для REQ_GET_FIELD и RES_GET_FIELD), и их значения не соответствуют значениям в перечислении MessageType (0 для REQ_LOGIN, 1 для REQ_GET_FIELD, 2 для RES_LOGIN и 3 для RES_GET_FIELD). Разве это не проблема?

Если вы хотите иметь согласованное количество перечислений, вы можете попробовать следующий подход:

enum MessageCategories
{
Request = 0,
Response,
AnythingElse
}
const int Watermark = 100;

это перечисление MessageCategories и const int Watermark являются общими для всех классов. Теперь вы можете переопределить свои перечисления следующим образом:

enum Request
{
REQ_LOGIN = MessageCategories::Request * Watermark,
REQ_GET_FIELD,
REQ_LAST_ITEM,
}
enum Response
{
RES_LOGIN = MessageCategories::Response * Watermark,
RES_GET_FIELD,
RES_LAST_ITEM,
}

В этом случае вам не нужно ваше перечисление MessageType, потому что все ваши коды перечислений согласованы.

0
ответ дан 8 December 2019 в 17:18
поделиться

почему бы вам просто не сделать что-то вроде этого:

void sendMessage (Request); void sendMessage (Ответить);

Простая перегрузка?

0
ответ дан 8 December 2019 в 17:18
поделиться

Возможно, не используя перечисления?

Я всегда чувствую себя ограниченным с перечислениями в C++... они просто не предлагают достаточно гибкости на мой вкус.

class MessageType
{
public:
  virtual ~MessageType();
  bool operator==(MessageType const& rhs) const;
  bool operator!=(MessageType const& rhs) const;
protected:
  MessageType(const char* type);
private:
  const char* mType;
};

class RequestType: public MessageType
{
public:
  static RequestType const Login() { return RequestType("Login"); }
  static RequestType const GetField { return RequestType("GetField"); }
protected:
  RequestType(const char* type);
};

// same for ResponseType

Здесь у вас есть полиморфное поведение, и вы можете ограничить клиента:

void someServerFunc(MessageType const& type);

void someClientFunc(RequestType const& type);

Тадаааам!

0
ответ дан 8 December 2019 в 17:18
поделиться
Другие вопросы по тегам:

Похожие вопросы: