在覆盖方法中返回不同的枚举
Returning different enum in overriden method
假设您必须在 C++03 中设计一个系统,您必须在其中管理来自不同来源的不同类型的消息。
所有消息都有一个共同的 属性,即 ID,该数字表示消息中包含的数据的含义。
所以ID是和来源相关的,不同的来源可以有其他来源的共同ID。即SourceA和SourceB可以发送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);
}
}
如您所见:没有神奇的数字,没有编译错误。
假设您必须在 C++03 中设计一个系统,您必须在其中管理来自不同来源的不同类型的消息。
所有消息都有一个共同的 属性,即 ID,该数字表示消息中包含的数据的含义。
所以ID是和来源相关的,不同的来源可以有其他来源的共同ID。即SourceA和SourceB可以发送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);
}
}
如您所见:没有神奇的数字,没有编译错误。