C++设计——网络数据包和序列化

标签 c++ inheritance serialization

对于我的游戏,我有一个 Packet 类,它表示网络数据包,基本上由一组数据和一些纯虚函数组成

然后我想要派生自 Packet 的类,例如:StatePacket、PauseRequestPacket 等。这些子类中的每一个都将实现虚函数 Handle(),当一个这些数据包中的一部分被接收,以便它可以完成它的工作,几个获取/设置函数将读取和设置数据数组中的字段。

所以我有两个问题:

  1. (抽象的)Packet 类需要是可复制和可分配的,但没有切片,保留派生类的所有字段。派生类甚至可能没有额外的字段,只有函数,可以与基类上的数组一起使用。我怎样才能做到这一点?
  2. 在序列化的时候,我会给每个子类一个唯一的数字ID,然后在子类自己序列化之前把它写到流中。但是对于反序列化,我如何将读取 ID 映射到适当的子类以实例化它?

如果有人需要任何说明,尽管问。

-- 谢谢


编辑:我对此不是很满意,但这就是我所管理的:

Packet.h: http://pastebin.com/f512e52f1
数据包.cpp:http://pastebin.com/f5d535d19
PacketFactory.h:http://pastebin.com/f29b7d637
PacketFactory.cpp:http://pastebin.com/f689edd9b
PacketAcknowledge.h: http://pastebin.com/f50f13d6f
PacketAcknowledge.cpp:http://pastebin.com/f62d34eef

如果有人有时间查看它并提出任何改进建议,我将不胜感激。


是的,我知道工厂模式,但我如何编写代码来构造每个类?一个巨大的 switch 语句?这也会重复每个类的 ID(一次在工厂中,一个在序列化器中),我想避免这种情况。

最佳答案

对于复制,你需要编写一个克隆函数,因为构造函数不能是虚拟的:

virtual Packet * clone() const = 0;

每个 Packet 实现都是这样实现的:

virtual Packet * clone() const {
    return new StatePacket(*this);
}

例如 StatePacket。数据包类应该是不可变的。一旦收到一个数据包,它的数据可以被复制出来,也可以被丢弃。因此不需要赋值运算符。将赋值运算符设为私有(private)且不定义它,这将有效地禁止分配包。

对于反序列化,您可以使用工厂模式:创建一个类,该类根据消息 ID 创建正确的消息类型。为此,您可以在已知的消息 ID 上使用 switch 语句,或者像这样的映射:

struct MessageFactory {
    std::map<Packet::IdType, Packet (*)()> map;

    MessageFactory() {
        map[StatePacket::Id] = &StatePacket::createInstance;
        // ... all other
    }

    Packet * createInstance(Packet::IdType id) {
        return map[id](); 
    }
} globalMessageFactory;

确实,您应该添加检查,例如 ID 是否真的为人所知等等。这只是粗略的想法。

关于C++设计——网络数据包和序列化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/329838/

相关文章:

c++ - 对整数的多维 vector 进行排序?

c++ - 如何在不输出新行的情况下更新终端中的输出字段?

c++ - 无法将 "derived"转换为其私有(private)基类 "base"

c# - 如何限制子类在 C# 中覆盖父类方法?

c++ - 需要类语法解释

java - 如何查明 JAVA 中导致 NotSerializedException 的原因

c++ - 异常处理 - 如果原始文件存在,则使用另一个文件名写入文件

c++ - 无法输出到文本文件,文件为空

php - 如何在 Symfony Serializer 中反序列化对象数组?

java - 将 ZonedDateTime 从 Dropwizard 保存到 MySQL 时出现问题