根据数据包类型更改行为,避免使用switch语句

时间:2019-05-14 07:46:43

标签: c++ inheritance switch-statement overloading

我正在用服务器-客户端体系结构编写程序,该程序主要通过数据包进行通信。我在想出一种更雄辩的方法来实现这一目标时遇到了麻烦。

这是我目前拥有的东西:

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转换。

1 个答案:

答案 0 :(得分:2)

您可以创建一个std :: functions向量,并使用_type作为索引。在每个索引处都有处理该特定类型数据包的功能。然后您的代码可能看起来像这样:

std::vector<std::function<void(Packet)>> handlers = { 
   player_joined_handler,
   player_quit_handler,
   message_sent_handler,
}

然后不用开关,您可以这样:

handlers[code](p);