C++ 中的多态枚举

发布于 2024-09-07 00:03:33 字数 593 浏览 6 评论 0原文

我有这些枚举声明:

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”通过网络发送它,另一方面我解析此类的对象并调度消息。但我有不同的客户;有些期望仅具有“Request”类型成员的对象,有些期望仅具有“Response”类型成员的对象。

使用“Message”类,我正在创建“DispatcherRequest”。

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


struct DispatcherRequest
{
..........
    Request type;
};

I have these Enum declarations:

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

Obviously I'm repeating elements in Enum's. Is there any way to prevent this?

EDIT:
I'm using "MessageType" on a general purpose class to send it through network, on the other side I parse the object of this class and dispatch message. But I have different clients; some expects only objects with "Request" type member and some expects only objects with "Response" type member.

Using "Message" class, I'm creating "DispatcherRequest"s.

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


struct DispatcherRequest
{
..........
    Request type;
};

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

不如归去 2024-09-14 00:03:33

为什么不尝试这样的事情呢?

enum MainType{  
    REQUEST,
    RESPONSE
};

enum SubType{
    LOGIN,
    GET_FIELD
};

class Message {
   MainType type;
   SubType sub_type;
   ...
};

Why not try something like this?

enum MainType{  
    REQUEST,
    RESPONSE
};

enum SubType{
    LOGIN,
    GET_FIELD
};

class Message {
   MainType type;
   SubType sub_type;
   ...
};
羁拥 2024-09-14 00:03:33

如果不知道这种设计背后的想法,这很难说,但您可能会考虑采用更面向对象的方法。大致如下:

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

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

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

This is hard to say without knowing the idea behind this design, but you might consider a more object-oriented approach. Something along the lines of:

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

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

class Response : public Message {
    public:
        virtual void send();
}
弱骨蛰伏 2024-09-14 00:03:33

您提到了多态枚举,为什么不只使用一种枚举并将其命名为您计划命名基本枚举的任何名称,例如“消息类型”?这将使您避免重复元素。

You allude to polymorphic enumerations, why not just use one enumeration and name it whatever you had planned on naming the base enumeration, say "Message Type"? This would keep you from repeating elements.

纵山崖 2024-09-14 00:03:33

如果我对 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;
};

In case my comment on PeterK's answer is as clear as mud, here's the resulting code:

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;
};
不甘平庸 2024-09-14 00:03:33

来自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
{
};

Spy from java (sorry for draft view):

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
{
};
三人与歌 2024-09-14 00:03:33

在您的代码示例中,枚举 Request 和枚举 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;

这个 enum 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,因为所有枚举代码都是一致的。

In your code example, values from enum Request and enum Response have the same values (0 for REQ_LOGIN and RES_LOGIN and 1 for REQ_GET_FIELD and RES_GET_FIELD), and their values do not comply with values in enum MessageType (0 for REQ_LOGIN, 1 for REQ_GET_FIELD, 2 for RES_LOGIN and 3 for RES_GET_FIELD). Isn't this a problem?

If you want to have consistent numbers of enums, you can try the following aproach:

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

this enum MessageCategories and const int Watermark are common to all classes.
Now you can redefine your enums like following:

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

In this case, you don't need your enum MessageType, because all your enum codes are consistent.

和我恋爱吧 2024-09-14 00:03:33

你为什么不做这样的事情:

void sendMessage(Request);
void sendMessage(Respond);

简单重载?

why won't you just do something like this:

void sendMessage(Request);
void sendMessage(Respond);

Simple overload?

和影子一齐双人舞 2024-09-14 00:03:33

也许不使用枚举?

我总是觉得 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);

Tadaaam!

Perhaps by not using enums ?

I always feel constrained with C++ enums... they just don't offer enough flexibility for my tastes.

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

Here you have polymorphic behavior, and you can restrict the client:

void someServerFunc(MessageType const& type);

void someClientFunc(RequestType const& type);

Tadaaam!

尴尬癌患者 2024-09-14 00:03:33

也许我针对这个问题给出的方法可能更适合您的设计目标。为了清楚起见,这里是适合您的问题的代码。

typedef struct{
    enum {
        LOGIN,
        GET_FIELD
    };
}MessageType;

typedef struct : public MessageType {
    //this struct inherits the fields of MessageType,
    //and can be accessed in code like so, Request::LOGIN or Request::GET_FIELD

    //omit this enum declaration if you do not wish to extend the base enum
    enum {
        //additional fields here
    };
}Request;

typedef struct : public MessageType {
    enum {
        //additional fields here
    };
}Response;

到目前为止,我遇到的唯一警告是,可以使用 ==Request 类型和 Response 类型的字段> 或 !=,无论两者是不同的类型。

如果在 C++11 中实现强类型枚举,情况可能并非如此,但我的编译器不支持该功能,因此我无法测试。

希望这有帮助。干杯!

perhaps the approach I gave in response to this question might better suit your design goals. For clarity, here is the code adapted to your question.

typedef struct{
    enum {
        LOGIN,
        GET_FIELD
    };
}MessageType;

typedef struct : public MessageType {
    //this struct inherits the fields of MessageType,
    //and can be accessed in code like so, Request::LOGIN or Request::GET_FIELD

    //omit this enum declaration if you do not wish to extend the base enum
    enum {
        //additional fields here
    };
}Request;

typedef struct : public MessageType {
    enum {
        //additional fields here
    };
}Response;

The only caveat I've encountered so far is that the fields of the Request type and Response type can be directly compared to each other using == or !=, regardless of the 2 being distinct types.

This might not be the case if implementing strongly typed enums in C++11, but my compiler doesn't support that feature, so I can't test.

Hope this helps. Cheers!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文