我正在尝试将对象的对象保存在二进制文件中。
以下是文件代码的一些负载:
template <class T> void read(T* obj,std::ifstream * file) {
file->read((char*)(obj),sizeof(*obj));
file->seekg(int(file->tellg())+sizeof(*obj));
}
void read_db(DB* obj,std::ifstream * file) {
read<DB>(obj,file);
for(int index = 0;index < obj->Arrays.size();index++) {
std::cin.get(); //debugging
obj->Arrays[0].Name = "hi"; //debugging
std::cin.get(); //debugging
std::cout << obj->Arrays[0].Name;
read<DB_ARRAY>(&obj->Arrays[index],file);
for(int row_index = 0;row_index < obj->Arrays[index].Rows.size();row_index++) {
read<DB_ROW>(&obj->Arrays[index].Rows[row_index],file);
for(int int_index = 0;int_index < obj->Arrays[index].Rows[row_index].i_Values.size();int_index++) {
read<DB_VALUE<int>>(&obj->Arrays[index].Rows[row_index].i_Values[int_index],file);
}
}
}
}
这是DB / DB_ARRAY类
class DB {
public:
std::string Name;
std::vector<DB_ARRAY> Arrays;
DB_ARRAY * operator[](std::string);
DB_ARRAY * Create(std::string);
};
class DB_ARRAY {
public:
DB* Parent;
std::string Name;
std::vector<DB_ROW> Rows;
DB_ROW * operator[](int);
DB_ROW * Create();
DB_ARRAY(DB*,std::string);
DB_ARRAY();
};
所以现在read_db函数的第一个参数将具有正确的值,并且对象上的向量Arrays具有正确的大小,但是如果我从obj-&gt; Arrays索引任何对象的任何值,它将抛出访问权限违规例外。
std::cout << obj->Arrays[0].Name; // error
std::cout << &obj->Arrays[0]; // no error
后者总是打印相同的地址,所以当我保存一个转换为char *的对象时,它是否也保存了它的地址?
答案 0 :(得分:0)
正如各种评论者指出的那样,你不能简单地通过保存/恢复它的内存来序列化(非POD)对象。
实现序列化的常用方法是在类上实现序列化接口。像这样:
struct ISerializable {
virtual std::ostream& save(std::ostream& os) const = 0;
virtual std::istream& load(std::istream& is) = 0;
};
然后,在可序列化的类中实现此接口,在引用其他可序列化类的任何成员上递归调用save
和load
,并写出任何POD成员。 E.g:
class DB_ARRAY : public ISerializable {
public:
DB* Parent;
std::string Name;
std::vector<DB_ROW> Rows;
DB_ROW * operator[](int);
DB_ROW * Create();
DB_ARRAY(DB*,std::string);
DB_ARRAY();
virtual std::ostream& save(std::ostream& os) const
{
// serialize out members
return os;
}
virtual std::istream& load(std::istream& is)
{
// unserialize members
return os;
}
};
正如 count0 指出的那样,boost::serialization也是一个很好的起点。
答案 1 :(得分:0)
文件中二进制数据的格式是什么?直到你指定
那,我们不能告诉你如何写它。基本上,你必须指定
所有数据类型的格式(char
除外),然后编写代码
逐字节写出该格式(或将其生成缓冲区);
另一方面,逐字节读取它,并重建它。
C ++标准没有说明(或很少)关于大小和
数据类型的表示,除了 sizeof(char)
必须是
1,unsigned char
必须是纯二进制表示
所有的比特。在我今天可以访问的机器上(Sun Sparc和
PC's),只有字符类型有一个共同的表示。至于
更复杂的类型,值表示中使用的内存
甚至可能不是连续的:一个按位的表示
例如,std::vector
通常是三个指针,实际上是
向量中的值完全在其他地方找到。
函数istream::read
和ostream::write
是
设计用于将数据读入缓冲区以进行手动解析和写入
预先格式化的缓冲区。你需要使用的事实
reinterpret_cast
使用它们应该是一个很好的指示
它不起作用。