在覆盖方法中返回不同的枚举

Returning different enum in overriden method

假设您必须在 C++03 中设计一个系统,您必须在其中管理来自不同来源的不同类型的消息。

所有消息都有一个共同的 属性,即 ID,该数字表示消息中包含的数据的含义

所以ID是和来源相关的,不同的来源可以有其他来源的共同ID。即SourceASourceB可以发送ID设置为1的消息,尽管消息中的数据含义完全不同。

因此表示消息的基 class 可以声明如下:

enum SourceType {
    SourceA,
    SourceB,
    // ...
};

struct Message {
    virtual int getID();
    virtual SourceType getSource();
    // ...
};

因为我想避免在我的代码周围散布 幻数 我想用一些更有意义的 enum 替换 int,但是由于每个来源都有自己不同的枚举是不可能的。

一个解决方案是使用 getSource 编辑的 return 信息将 int 转换为正确的 enum,但这似乎是一个非常完美的设计。

另一种解决方案是为所有具有大量重复值(这不是错误)的源定义一个包含所有可能 ID 的大枚举,如下所示:

enum MessageID {
    SourceA_ID1,
    SourceA_ID2,
    SourceB_ID1,
    SourceB_ID2,
    // ...
};

所以 getID 消息可以 return MessageID,但这意味着 MessageID 的大小会爆炸式增长,维护和记录可能会有点混乱。

选择第一个备选方案:

One solution could be casting the int to the proper enum using the information returned by getSource, but it seems a very flawless design.

基本上enum等于int。它作为一种创建常量和避免代码中出现幻数的简单方法而存在。所以可能有:

enum SourceType {
    SourceA,
    SourceB,
    // ...
};

struct Message {
    virtual int getID();
    virtual SourceType getSource();
    // ...
};

// Maybe in "sourceA.h"
enum SourceA_Ids {
    SourceA_ID1 = 1, 
    SourceA_ID2 = 12, 
    SourceA_ID3 = 20
};

// Maybe in "sourceB.h"
enum SourceB_Ids {
    SourceB_ID1 = 1, 
    SourceB_ID2 = 2, 
    SourceB_ID3 = 3
};

并且在您的代码中,直接进行赋值和比较而无需转换任何内容,因为 enum 到 int 是隐式的:

// sourceA.h
struct MessageFromSourceA: Message {
    double data;
    ...
    MessageFromSourceA() {
        source = SourceA;
        data = 0;
    }
};

// sourceA.cpp
void processMsgFromSourceA(Message &msg) {
    if (msg.getID() == SourceA_ID1) {
        // Send an answer
        MessageFromSourceA msga;
        msga.id = SourceA_ID2;
        msga.data = 123.456;
        send(msga);
    }
}

如您所见:没有神奇的数字,没有编译错误。