C++:如何在不使用库的情况下序列化/反序列化对象?

Win*_*nte 10 c++ serialization deserialization

我试图理解序列化/反序列化如何在不使用库的情况下在C++中工作.我从简单的对象开始,但是当反序列化向量时,我发现,如果没有先写入它的大小,我就无法获得向量.而且,我不知道应该选择哪种文件格式,因为如果在向量大小之前存在数字,我就无法正确读取它.此外,我想用类和映射容器来做到这一点.我的任务是序列化/反序列化这样的对象:

PersonInfo
{
    unsigned int    age_;
    string name_;
    enum { undef, man, woman } sex_;
}

Person : PersonInfo 
{
    vector<Person>      children_;
    map<string, PersonInfo>     addrBook_;
}
Run Code Online (Sandbox Code Playgroud)

目前我知道如何序列化这样的简单对象:

vector<PersonInfo> vecPersonInfo;
vecPersonInfo.push_back(*personInfo);
vecPersonInfo.push_back(*oneMorePersonInfo);

ofstream file("file", ios::out | ios::binary);
if (!file) {
    cout<<"can not open file";
} else {
    vector<PersonInfo>::const_iterator iterator = vecPersonInfo.begin();
    for (; iterator != vecPersonInfo.end(); iterator++) {
        file<<*iterator;
    }
Run Code Online (Sandbox Code Playgroud)

能否请您建议,我如何为这个复杂的对象或一个能够清楚解释它的好教程做到这一点?

Vit*_*con 13

一种模式是实现一个抽象类,定义序列化函数,类定义进入序列化器的内容以及出现的内容.一个例子是:

class Serializable
{
public:
    Serializable(){}
    virtual ~Serializable(){}

    virtual void serialize(std::ostream& stream) = 0;
    virtual void deserialize(std::istream& stream) = 0;
};
Run Code Online (Sandbox Code Playgroud)

然后,为要序列化的类/结构实现Serializable接口:

struct PersonInfo : public Serializable // Yes! It's possible
{
    unsigned int age_;
    string name_;
    enum { undef, man, woman } sex_;

    virtual void serialize(std::ostream& stream)
    {
        // Serialization code
        stream << age_ << name_ << sex_;
    }

    virtual void deserialize(std::istream& stream)
    {
        // Deserialization code
        stream >> age_ >> name_ >> sex_;
    }
};
Run Code Online (Sandbox Code Playgroud)

休息我相信你知道.这里有几个障碍可以通过你的闲暇来完成:

  1. 当你在一个字符串中写入一个带有空格的字符串并尝试将其读回时,你将只得到它的一部分而字符串的其余部分会"破坏"之后读取的值.
  2. 你如何编程它是跨平台的(小端与大端)
  3. 您的程序如何自动检测反序列化时要创建的类.

线索:

  1. 使用具有写bool,int,float,strings等函数的自定义序列化程序.
  2. 使用字符串表示要序列化的对象类型,并使用factory在反序列化时创建该对象的实例.
  3. 使用预定义的宏来确定正在编译代码的平台.
  4. 始终以固定的endian编写文件,并使使用其他endianess的平台进行调整.

  • 这会失败,因为您没有添加分隔符,性别(枚举值)将被读取为名称的一部分。此外,如果名称有多个单词,则只会读取其中的第一个...问题比提供的简单解决方案要复杂一些。 (3认同)