C ++中的简单序列化和反序列化

时间:2015-03-16 17:43:18

标签: c++ serialization polymorphism

我需要一种方法来序列化不同类型的对象(但是从同一个类派生的类型),然后将它们反序列化为包含派生类的基类的指针。例如:

#include<iostream>
#include<fstream>
class One
{
public:
    int a;
    virtual void Func()
    {
    }
};

class One1: public One
{
    char s[128];
    void Func1(int l)
    {
        std::cout<<l<<'\n';
    }
    void Func()
    {
         Func1(156);
    }
};

int main()
{
    One* x = new One1;
    x->Func();
    char* y=(char*)x;
    delete x;
    /*std::ofstream out("test11.txt",std::ofstream::out | std::ofstream::trunc);
    out.write(y,sizeof(One1));
    out.close();
    std::ifstream in("test11.txt",std::ifstream::in);
    char* y1=new char[sizeof(One1)];
    in.read(y1,sizeof(One1));*/
    One* z=(One*)y/*1*/;
    z->Func();
    return 0;
}

此代码输出

156
156

但是当我取消注释注释时(当我尝试将文件写入对象的 char 表示并从该文件读取时),程序输出156并结束试图执行z->Func();时出现分段错误。我检查了变量y的内容与y1的内容不同。为什么呢?
这个问题的原因是什么?我如何解决它(可能通过使用一些特殊的库)?

1 个答案:

答案 0 :(得分:2)

1。不要通过简单地复制字节

来序列化派生类

您不能简单地通过将多态对象转换为字节数组来编写多态对象,然后通过二进制read加载它们。具有虚函数的类存储指向vtable中的实现的指针。转储派生类的实例将导致转储存储在vtable中的指针,显然,在再次运行程序之后,它不必是有效的指针。之后访问它很可能会产生分段错误。

如果您真的想使用 easy 方式(直接读取和写入字节),请使用POD类。

2。不要访问无效指针

虽然以上是答案中最重要的部分(因为它会完全改变你的程序),但还有其他一些事情需要加以强调。命令:

char* y=(char*)x;

创建一个char指针,指向x地址不会复制对象。因此,当你以后做:

delete x;

指向y的指针变为无效。当您稍后尝试将其写入文件时:

std::ofstream out("test11.txt",std::ofstream::out | std::ofstream::trunc);
out.write(y,sizeof(One1));

您可以访问不属于您的内存。至少不再这样了,因为你特别说你不需要它,通过早先打电话给delete