У меня есть эти Перечислимые объявления:
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;
};
Почему бы не попробовать что-то подобное?
enum MainType{
REQUEST,
RESPONSE
};
enum SubType{
LOGIN,
GET_FIELD
};
class Message {
MainType type;
SubType sub_type;
...
};
Трудно сказать, не зная идеи, лежащей в основе этого дизайна, но вы могли бы рассмотреть более объектно-ориентированный подход. Что-то вроде:
class Message {
public:
virtual void send() = 0;
};
class Request : public Message {
public:
virtual void send();
}
class Response : public Message {
public:
virtual void send();
}
Вы ссылаетесь на полиморфные перечисления, почему бы просто не использовать одно перечисление и назвать его так, как вы планировали назвать базовое перечисление, скажем «Тип сообщения»? Это убережет вас от повторения элементов.
Если мой комментарий к ответу 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;
};
Шпион из 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
{
};
В вашем примере кода значения из 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, потому что все ваши коды перечислений согласованы.
почему бы вам просто не сделать что-то вроде этого:
void sendMessage (Request);
void sendMessage (Ответить);
Простая перегрузка?
Возможно, не используя перечисления?
Я всегда чувствую себя ограниченным с перечислениями в 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);
Тадаааам!