我正在用服务器-客户端体系结构编写程序,该程序主要通过数据包进行通信。我在想出一种更雄辩的方法来实现这一目标时遇到了麻烦。
这是我目前拥有的东西:
namespace Packet {
enum class TCP {
PLAYER_JOINED,
PLAYER_QUIT,
MESSAGE_SENT
};
}
伴随这些函数将类型转换为整数代码,反之亦然:
constexpr auto toInt(Packet::TCP _t) {
return static_cast<std::underlying_type_t<Packet::TCP>>(_t);
}
constexpr Packet::TCP toTCPType(int _i) {
return static_cast<Packet::TCP>(_i);
}
在我的网络管理器代码中,我目前有一个要避免的丑陋的switch语句。与其当前不同的是:
void sendPacket(Packet::TCP _type) {
int code{Packet::toInt(_type);
Packet p;
p << code;
switch (_type) {
case Packet::TCP::PLAYER_JOINED:
//do stuff and operate on p
break;
case Packet::TCP::PLAYER_QUIT:
//do stuff and operate on p
break;
//etc.
}
}
如果可能是这样,我会更愿意:
void preparePacket(Packet::TCP _type) {
//common behaviour that has to be done no matter the type
int code{Packet::toInt(_type);
Packet p;
p << code;
sendPacket(_type, p);
}
不过,我遇到了几个障碍。显然,我无法在TCP枚举的值上重载sendPacket。我可以使每个枚举器类型具有其自己的结构,但是随后我失去了将数据包快速转换为int的能力,这对于接收者知道它是哪种数据包至关重要。可以通过添加一个虚拟的getId()函数来解决,但是那只是一种单向转换(从包到整数),而我还需要以某种方式从int到Packet转换。
答案 0 :(得分:2)
您可以创建一个std :: functions向量,并使用_type作为索引。在每个索引处都有处理该特定类型数据包的功能。然后您的代码可能看起来像这样:
std::vector<std::function<void(Packet)>> handlers = {
player_joined_handler,
player_quit_handler,
message_sent_handler,
}
然后不用开关,您可以这样:
handlers[code](p);