嗨我目前正在研究一个模拟程序,它试图将程序的状态(变量和对象)保存到二进制文件中,以便它可以恢复如果需要模拟。使用虚拟方法将对象写入和读取到二进制文件
就像一个笔记:我知道这是不同的CPU架构不兼容,这是绝对好!
在编写具有虚拟方法的对象到文件然后尝试读取它之前,一切似乎都能正常工作。
下面的代码说明了此问题:
header.hpp
using namespace std;
class parent
{
public:
int mValue;
virtual string getName() =0;
virtual size_t getSize() =0;
parent(int value) : mValue(value)
{
}
};
class bob : public parent
{
public:
bob(int value) : parent(value)
{
}
string getName();
size_t getSize() { return sizeof(bob); }
};
string bob::getName()
{
string name("bob");
return name;
}
class sarah : public parent
{
public:
sarah(int value) : parent(value)
{
}
string getName();
size_t getSize() { return sizeof(sarah); }
};
string sarah::getName()
{
string name("sarah");
return name;
}
write.cpp
#include <iostream>
#include <fstream>
#include <string>
#include "header.hpp"
int main()
{
sarah girl(1);
bob boy(2);
parent* child1 = &girl;
parent* child2 = &boy;
cout << "Created child called " << child1->getName() << endl;
cout << "Created child called " << child2->getName() << endl;
//save sarah and bob to a binary file
ofstream file("temp.bin", ios::binary | ios::trunc);
if(!file.is_open())
return 1;
//format <size><data><size><data>....
size_t tempSize=0;
//write child1
tempSize = child1->getSize();
file.write((char*) &tempSize,sizeof(size_t));
file.write((char*) child1,tempSize);
tempSize = child2->getSize();
file.write((char*) &tempSize,sizeof(size_t));
file.write((char*) child2,tempSize);
file.close();
return 0;
}
read.cpp
#include <iostream>
#include <fstream>
#include <string>
#include <cstdlib>
#include "header.hpp"
int main()
{
//read sarah and bob from a binary file
ifstream file("temp.bin", ios::binary);
//format <size><data><size><data>....
size_t tempSize=0;
//get size of child1
file.read((char*) &tempSize, sizeof(size_t));
//allocate memory for child1
parent* child1= (parent*) malloc(tempSize);
//read child 1 back
file.read((char*) child1,tempSize);
//get size of child2
file.read((char*) &tempSize, sizeof(size_t));
//allocate memory for child2
parent* child2= (parent*) malloc(tempSize);
//read child 2 back
file.read((char*) child2,tempSize);
file.close();
//Using virtual methods causes SEGFAULT
cout << "Recreated child" << child1->getName() << endl;
cout << "Recreated child" << child2->getName() << endl;
return 0;
}
建设及运营如下:
g++ -g write.cpp -o write ; ./write
g++ -g read.cpp -o read ; ./read
当我通过读程序在gdb一步我已经注意到这个问题似乎是v表指针。当我在读程序中重新创建“sarah”(child1)时,v表指针是写程序存在的指针,而不是读程序。所以大概这个写程序中这个“sarah”的v表指针指向一个导致SEGFAULT的无效内存区域。
我有两个问题:
是否有可能在V表指针信息保存到二进制文件中的“写”方案,让我的对象是在“正确”的程序完全重建而不诉诸像Boost :: Serialization或POST ++这样的库来为我处理这个问题?
如果这是不可能的,或者它非常复杂,那么我将不得不添加一个构造函数和一个“saveState()”方法(它们可以分别作用于ifstream和ofstream对象),以便每个类(在这种情况下sarah和bob)处理保存并从二进制文件读取它的状态。问题在于我有多个派生自类“parent”的类,所以我需要一种方法让“读取”程序计算出读取二进制文件时调用哪个构造函数。
我想出了一种方法来确定调用哪个构造函数。这将是
给予每一个从“父”的唯一ID
- 在“写”程序得出的二进制文件
添加唯一的ID在“读”程序读取每个唯一的类ID,然后使用switch语句调用相关的构造函数。
这不是很优雅,但每当我添加一个派生自“父”的新类时,我必须给它一个ID并将它添加到“读”中的switch语句中。有没有更好的方法来做到这一点?
感谢您的阅读,我知道我的帖子很长!