1. 一个非常简单的情形
输出档案(archive)类似于输出数据流(stream)。数据能通过<< 或 & 操作符存储到档案(archive)中:
ar << data;
ar & data;
输入档案(archive)类似于输入数据流(stream)。数据能通过>> 或 & 操作符从档案(archive)中装载。
ar >> data;
ar & data;
对于原始数据类型,当这些操作调用的时候,数据是简单的“被存储/被装载” “到/从” 档案(archive)。对于类(class)数据类型,类的serialize 函数被调用。对上面的操作,每个serialize 函数用来“存储/装载”其数据成员。这个处理采用递归的方式,直到所有包含在类中的数据“被存储/被装载”。
一个非常简单的情形
通常用serialize 函数来存储和装载类的数据成员。
这个库包含一个叫 demo.cpp 的程序,用于介绍如何用这个库。下面,我们从这个demo摘录代码,来介绍这个库应用的最简单情形。
#include <fstream>
// include headers that implement a archive in simple text format
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
/////////////////////////////////////////////////////////////
// gps coordinate
//
// illustrates serialization for a simple type
//
class gps_position
{
private:
friend class boost::serialization::access;
// When the class Archive corresponds to an output archive, the
// & operator is defined similar to <<. Likewise, when the class Archive
// is a type of input archive the & operator is defined similar to >>.
// 这个模板函数序列化时被boost库调用
template<class Archive>
void serialize(Archive & ar, const unsigned int version)
{
ar & degrees;
ar & minutes;
ar & seconds;
}
int degrees;
int minutes;
float seconds;
public:
gps_position(){};
gps_position(int d, int m, float s) :
degrees(d), minutes(m), seconds(s)
{}
};
int main()
{
// create and open a character archive for output
std::ofstream ofs("filename");
boost::archive::text_oarchive oa(ofs);
// create class instance
const gps_position g(35, 59, 24.567f);
// write class instance to archive
oa << g;
// close archive
ofs.close();
// ... some time later restore the class instance to its orginal state
// create and open an archive for input
std::ifstream ifs("filename", std::ios::binary);
boost::archive::text_iarchive ia(ifs);
// read class state from archive
gps_position newg;
ia >> newg;
// close archive
ifs.close();
return 0;
}
对于每个通过序列化“被存储”的类,必须存在一个函数去实现“存储”其所有状态数据。对于每个通过序列化“被装载”的类,必须存在一个函数来实现“装载”其所有状态数据。在上面的例子中,这些函数是模板成员函数serialize。
2. 非侵入的版本
在上例是侵入的设计。类是需要由其实例来序列化,来改变。这在某些情形是困难的。一个等价的可选的设计如下:
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
class gps_position
{
public:
int degrees;
int minutes;
float seconds;
gps_position(){};
gps_position(int d, int m, float s) :
degrees(d), minutes(m), seconds(s)
{}
};
// 注意命名空间
namespace boost {
namespace serialization {
template<class Archive>
void serialize(Archive & ar, gps_position & g, const unsigned int version)
{
ar & g.degrees;
ar & g.minutes;
ar & g.seconds;
}
} // namespace serialization
} // namespace boost
这种情况生成的serialize 函数不是gps_position类的成员函数。这有异曲同工之妙。
非侵入序列化主要应用在不改变类定义就可实现类的序列化。为实现这种可能,类必须提供足够的信息来更新类状态。在这个例子中,我们假设类有public成员。仅当提供足够信息来存储和装载的类,才能不改变类自身,在外部来序列化类状态。
责任编辑:小草