Boost::Serialization试用手记
2014-10-21 17:42
155 查看
对于核心数据相对比较集中的应用程序来说,serialization机制可以直接充当文档保存与打开功能的实现工具,这也是很多成熟的应用程序framework都提供serialization支持的原因
但是个人认为,serialization最精彩的用处在于保存现场,比如在探索性的科研应用程序开发过程中,很可能一部分算法已经固定下来,其余的有待进一步探索,而确定下来的部分有可能十分time consuming,如果每次改一下算法都要从头计算,就会很费时间,长期下去对工作情绪会有很大影响,这时候可以用serialization把每一步的结果存成文件,下次启动时任选一个开始新的计算。
Boost的Serialization库是一个十分强大的工具,它文档中提到的11个开发目标列举如下:
1.代码移植性,只依赖于ANSI C++标准
2.代码简洁性,的确运用Boost::Serialization所需要的代码量很小
3.每个类有自己独立的版本控制,以保证旧的save结果可以被新的程序load回来
4.深度指针save与load,不仅serialize指针本身,而且包括它指向的对象数据
5.多个指针指向同一个对象不会被serialize多次
6.对常用STL容器的支持
7.串行数据的平台移植性
8.类如何被串行化与串行数据按何种格式存储相互无关
9.非侵入性,这对于数据中使用了第三方类库的情形很有效
最后两个没有理解,希望高人指点
10.The archive interface must be simple enough to easily permit creation of a new type of archive.
11.The archive interface must be rich enough to permit the creation of an archive that presents serialized data as XML in a useful manner.
下面是我试用Boost::Serialization的记录
第一个例子
假设有这样一个类需要串行化
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
class Data
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
public :
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
int mInt;
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
} ;
这里为了简化起见,成员变量都设成public了,串行化的代码如下
1
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
#include < fstream >
2
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
3
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
// fewest include headers
4
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
#include < boost / archive / text_iarchive.hpp >
5
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
#include < boost / archive / text_oarchive.hpp >
6
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
7
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
// use this to ease the archive selection
8
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
typedef boost::archive::text_iarchive iarchive;
9
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
typedef boost::archive::text_oarchive oarchive;
10
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
11
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
class Data
12
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
13
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
friend class boost::serialization::access;
14
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
15
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
protected :
16
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
17
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
template < class Archive >
18
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
void serialize(Archive & ar, const unsigned int /* file_version */ )
19
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
20
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
ar & mInt;
21
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
22
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
23
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
public :
24
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
25
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
int mInt;
26
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
27
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
static void saveData( const Data & obj, std:: string fileName)
28
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
29
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
std::ofstream ofs(fileName.c_str());
30
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
oarchive oa(ofs);
31
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
oa << obj;
32
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
33
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
34
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
static void loadData(Data & obj, std:: string fileName)
35
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
36
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
std::ifstream ifs(fileName.c_str());
37
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
iarchive ia(ifs);
38
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
ia >> obj;
39
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
40
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
} ;
41
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
42
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
void main()
43
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
44
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
Data d1;
45
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
d1.mInt = 3 ;
46
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
47
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
Data::saveData(d1, " output.txt " );
48
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
49
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
Data d2;
50
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
Data::loadData(d2, " output.txt " );
51
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
52
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
// results should be the same.
53
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
ToolLib::LOG(TOSTR(d2.mInt));
54
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
}
成员serialize函数是定义类如何被串行化之规则的核心。
由于使用了RTTI机制,serialize函数不需要为virtual,永远只要是void就可以,在串行化指针的时候能够被正确调用。
serialize函数中的 & 运算符在load时调用 >>,而在save时调用 <<,这样save和load只要一个函数就可以。
saveData和loadData函数必不可少,由于serialization库强大的编译检查机制,如果不用这样的方式来save一个对象,往往会因为这个对象不是const而编译失败。
所用的archive类型可以任选,如text或binary,上例中的typedef即是为了封装这一变化
非侵入性
下面一例演示了串行化不可侵入的类型。这里用的是 WildMagicLib2.5中的 2-Vector
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
#include < WildMagic2p5 / Include / WmlVector2.h >
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
class Data
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
friend class boost::serialization::access;
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
protected :
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
template < class Archive >
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
void serialize(Archive & ar, const unsigned int /* file_version */ )
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
ar & mVec2d;
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
public :
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
Wml::Vector2d mVec2d;
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
static void saveData( const Data & obj, std:: string fileName);
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
static void loadData(Data & obj, std:: string fileName);
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
} ;
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
namespace boost {
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
namespace serialization {
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
template < class Archive, class Real >
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
void serialize(Archive & ar, Wml::Vector2 < Real >& g, const unsigned int version)
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
ar & g.X();
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
ar & g.Y();
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
} // namespace serialization
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
} // namespace boost
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
这种情况下,需要这个全局serialize在能够访问到那个类里需要串行化的数据,常常load和save的方法不一样,如load时调用setVar,save时调用getVar,这时Archive::is_loading和Archive::is_saving常数就有用了。一种等价但是更直观的方法是使用BOOST_SERIALIZATION_SPLIT_MEMBER或者BOOST_SERIALIZATION_SPLIT_FREE宏,两者分别生成调用load/save成员函数和load/save全局函数的代码。
在serialization内部,是通过定义全局serialize函数模板,并在里面调用成员serialize函数来实现的,如下所示,需要非侵入的对象只要特化这个全局函数就可以了。
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
// default implemenation - call the member function "serialize"
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
template < class Archive, class T >
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
inline void serialize(
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
Archive & ar, T & t, const BOOST_PFTO unsigned int file_version
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
) {
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
access::serialize(ar, t, static_cast < unsigned int > (file_version));
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
}
STL容器支持
通过包含一些serialization提供的头文件,对STL容器可以像普通变量一样支持
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
// STL support headers
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
#include < boost / serialization / vector.hpp >
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
#include < boost / serialization / string .hpp >
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
class Data
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
friend class boost::serialization::access;
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
protected :
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
template < class Archive >
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
void serialize(Archive & ar, const unsigned int /* file_version */ )
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
ar & mStr;
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
ar & mVecInt;
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
ar & mVecStr;
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
public :
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
std:: string mStr;
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
std::vector < int > mVecInt;
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
std::vector < std:: string > mVecStr;
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
static void saveData( const Data & obj, std:: string fileName);
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
static void loadData(Data & obj, std:: string fileName);
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
} ;
指针与数组
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
class ClassA
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
public :
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
int mInt;
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
} ;
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
class Data
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
friend class boost::serialization::access;
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
protected :
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
template < class Archive >
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
void serialize(Archive & ar, const unsigned int /* file_version */ )
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
ar & mPtrInt;
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
ar & mArrInt;
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
ar & mPtrData;
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
ar & mPtrA;
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
public :
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Data():mPtrData(NULL), mPtrInt(NULL), mPtrA(NULL) {}
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
Data * mPtrData;
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
int mArrInt[ 10 ];
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
int * mPtrInt;
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
ClassA * mPtrA;
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
static void saveData( const Data & obj, std:: string fileName);
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
static void loadData(Data & obj, std:: string fileName);
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
} ;
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
namespace boost {
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
namespace serialization {
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
template < class Archive >
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
void serialize(Archive & ar, int & g, const unsigned int version)
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
ar & g;
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
} // namespace serialization
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
} // namespace boost
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
数组可以直接串行化,指针比须保证有效,所以必须保证在串行化之前经过初始化。
对于基本类型如int,可以直接串行化,但其指针int*,要当作不可侵入类型的指针来看待,所以需要一个全局serialize函数来说明int类型的串行化方式
对于有基类指针的串行化,代码如下
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
class ClassA
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
public :
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
int mIntA;
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
virtual void someMethod() = NULL;
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
template < class Archive >
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
void serialize(Archive & ar, const unsigned int /* file_version */ )
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
ar & mIntB;
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
} ;
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
BOOST_IS_ABSTRACT(ClassA)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
class ClassB: public ClassA
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
public :
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
int mIntB;
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
virtual void someMethod() {}
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
template < class Archive >
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
void serialize(Archive & ar, const unsigned int /* file_version */ )
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
ar & boost::serialization::base_object < ClassA > ( * this );
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
ar & mIntB;
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
} ;
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
BOOST_CLASS_EXPORT(ClassB)
纯虚类后加上BOOST_ISABSTRACT,而可能会被串行化到的子类用BOOST_CLASS_EXPORT,这样就可以在任何地方串行化 ClassA* 的成员变量。
子类的serialize函数里必须要照顾到基类的成员。
版本控制
在serialize函数中的version参数就是用于版本控制的,所有类的版本号默认为0,新版本的类可以自己指定版本号以便与旧版本相区别。如下
BOOST_CLASS_VERSION(ClassA, 1)
对于save过程,版本号始终为新的,而load过程取决于文件中保存的值,对于新版本新增变量的情况可以这样解决
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
// old definition
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
class ClassA
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
public :
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
int mInt;
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
} ;
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
// new definition
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
class ClassA
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
public :
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
int mInt;
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
int mIntNew;
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
template < class Archive >
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
void serialize(Archive & ar, const unsigned int ver)
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
ar & mInt;
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
if (ver == 1 )
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
ar & mIntB;
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
} ;
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
BOOST_CLASS_VERSION(ClassA, 1 )
对于有改动的情形,稍微复杂一点,可以这样
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
// old definition
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
class ClassA
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
public :
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
TypeA mVarA;
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
} ;
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
// new definition
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
class ClassA
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
public :
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
// suppose now we use B and C instead of A
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
TypeB mVarB;
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
TypeC mVarC;
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
template < class Archive >
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
void serialize(Archive & ar, const unsigned int ver)
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
if (ver < 1 )
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
// here must be loading
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
TypeA varA;
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
ar & varA;
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
// now derive mVarB & mVarC from varA;
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
else
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
ar & mVarB;
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
ar & mVarC;
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
} ;
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
BOOST_CLASS_VERSION(ClassA, 1 )
但是个人认为,serialization最精彩的用处在于保存现场,比如在探索性的科研应用程序开发过程中,很可能一部分算法已经固定下来,其余的有待进一步探索,而确定下来的部分有可能十分time consuming,如果每次改一下算法都要从头计算,就会很费时间,长期下去对工作情绪会有很大影响,这时候可以用serialization把每一步的结果存成文件,下次启动时任选一个开始新的计算。
Boost的Serialization库是一个十分强大的工具,它文档中提到的11个开发目标列举如下:
1.代码移植性,只依赖于ANSI C++标准
2.代码简洁性,的确运用Boost::Serialization所需要的代码量很小
3.每个类有自己独立的版本控制,以保证旧的save结果可以被新的程序load回来
4.深度指针save与load,不仅serialize指针本身,而且包括它指向的对象数据
5.多个指针指向同一个对象不会被serialize多次
6.对常用STL容器的支持
7.串行数据的平台移植性
8.类如何被串行化与串行数据按何种格式存储相互无关
9.非侵入性,这对于数据中使用了第三方类库的情形很有效
最后两个没有理解,希望高人指点
10.The archive interface must be simple enough to easily permit creation of a new type of archive.
11.The archive interface must be rich enough to permit the creation of an archive that presents serialized data as XML in a useful manner.
下面是我试用Boost::Serialization的记录
第一个例子
假设有这样一个类需要串行化
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
class Data
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
public :
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
int mInt;
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
} ;
这里为了简化起见,成员变量都设成public了,串行化的代码如下
1
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
#include < fstream >
2
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
3
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
// fewest include headers
4
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
#include < boost / archive / text_iarchive.hpp >
5
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
#include < boost / archive / text_oarchive.hpp >
6
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
7
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
// use this to ease the archive selection
8
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
typedef boost::archive::text_iarchive iarchive;
9
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
typedef boost::archive::text_oarchive oarchive;
10
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
11
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
class Data
12
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
13
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
friend class boost::serialization::access;
14
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
15
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
protected :
16
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
17
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
template < class Archive >
18
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
void serialize(Archive & ar, const unsigned int /* file_version */ )
19
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
20
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
ar & mInt;
21
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
22
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
23
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
public :
24
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
25
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
int mInt;
26
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
27
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
static void saveData( const Data & obj, std:: string fileName)
28
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
29
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
std::ofstream ofs(fileName.c_str());
30
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
oarchive oa(ofs);
31
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
oa << obj;
32
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
33
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
34
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
static void loadData(Data & obj, std:: string fileName)
35
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
36
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
std::ifstream ifs(fileName.c_str());
37
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
iarchive ia(ifs);
38
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
ia >> obj;
39
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
40
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
} ;
41
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
42
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
void main()
43
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
44
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
Data d1;
45
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
d1.mInt = 3 ;
46
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
47
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
Data::saveData(d1, " output.txt " );
48
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
49
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
Data d2;
50
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
Data::loadData(d2, " output.txt " );
51
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
52
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
// results should be the same.
53
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
ToolLib::LOG(TOSTR(d2.mInt));
54
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
}
成员serialize函数是定义类如何被串行化之规则的核心。
由于使用了RTTI机制,serialize函数不需要为virtual,永远只要是void就可以,在串行化指针的时候能够被正确调用。
serialize函数中的 & 运算符在load时调用 >>,而在save时调用 <<,这样save和load只要一个函数就可以。
saveData和loadData函数必不可少,由于serialization库强大的编译检查机制,如果不用这样的方式来save一个对象,往往会因为这个对象不是const而编译失败。
所用的archive类型可以任选,如text或binary,上例中的typedef即是为了封装这一变化
非侵入性
下面一例演示了串行化不可侵入的类型。这里用的是 WildMagicLib2.5中的 2-Vector
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
#include < WildMagic2p5 / Include / WmlVector2.h >
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
class Data
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
friend class boost::serialization::access;
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
protected :
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
template < class Archive >
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
void serialize(Archive & ar, const unsigned int /* file_version */ )
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
ar & mVec2d;
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
public :
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
Wml::Vector2d mVec2d;
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
static void saveData( const Data & obj, std:: string fileName);
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
static void loadData(Data & obj, std:: string fileName);
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
} ;
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
namespace boost {
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
namespace serialization {
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
template < class Archive, class Real >
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
void serialize(Archive & ar, Wml::Vector2 < Real >& g, const unsigned int version)
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
ar & g.X();
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
ar & g.Y();
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
} // namespace serialization
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
} // namespace boost
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
这种情况下,需要这个全局serialize在能够访问到那个类里需要串行化的数据,常常load和save的方法不一样,如load时调用setVar,save时调用getVar,这时Archive::is_loading和Archive::is_saving常数就有用了。一种等价但是更直观的方法是使用BOOST_SERIALIZATION_SPLIT_MEMBER或者BOOST_SERIALIZATION_SPLIT_FREE宏,两者分别生成调用load/save成员函数和load/save全局函数的代码。
在serialization内部,是通过定义全局serialize函数模板,并在里面调用成员serialize函数来实现的,如下所示,需要非侵入的对象只要特化这个全局函数就可以了。
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
// default implemenation - call the member function "serialize"
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
template < class Archive, class T >
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
inline void serialize(
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
Archive & ar, T & t, const BOOST_PFTO unsigned int file_version
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
) {
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
access::serialize(ar, t, static_cast < unsigned int > (file_version));
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
}
STL容器支持
通过包含一些serialization提供的头文件,对STL容器可以像普通变量一样支持
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
// STL support headers
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
#include < boost / serialization / vector.hpp >
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
#include < boost / serialization / string .hpp >
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
class Data
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
friend class boost::serialization::access;
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
protected :
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
template < class Archive >
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
void serialize(Archive & ar, const unsigned int /* file_version */ )
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
ar & mStr;
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
ar & mVecInt;
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
ar & mVecStr;
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
public :
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
std:: string mStr;
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
std::vector < int > mVecInt;
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
std::vector < std:: string > mVecStr;
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
static void saveData( const Data & obj, std:: string fileName);
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
static void loadData(Data & obj, std:: string fileName);
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
} ;
指针与数组
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
class ClassA
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
public :
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
int mInt;
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
} ;
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
class Data
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
friend class boost::serialization::access;
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
protected :
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
template < class Archive >
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
void serialize(Archive & ar, const unsigned int /* file_version */ )
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
ar & mPtrInt;
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
ar & mArrInt;
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
ar & mPtrData;
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
ar & mPtrA;
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
public :
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Data():mPtrData(NULL), mPtrInt(NULL), mPtrA(NULL) {}
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
Data * mPtrData;
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
int mArrInt[ 10 ];
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
int * mPtrInt;
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
ClassA * mPtrA;
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
static void saveData( const Data & obj, std:: string fileName);
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
static void loadData(Data & obj, std:: string fileName);
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
} ;
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
namespace boost {
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
namespace serialization {
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
template < class Archive >
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
void serialize(Archive & ar, int & g, const unsigned int version)
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
ar & g;
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
} // namespace serialization
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
} // namespace boost
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
数组可以直接串行化,指针比须保证有效,所以必须保证在串行化之前经过初始化。
对于基本类型如int,可以直接串行化,但其指针int*,要当作不可侵入类型的指针来看待,所以需要一个全局serialize函数来说明int类型的串行化方式
对于有基类指针的串行化,代码如下
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
class ClassA
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
public :
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
int mIntA;
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
virtual void someMethod() = NULL;
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
template < class Archive >
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
void serialize(Archive & ar, const unsigned int /* file_version */ )
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
ar & mIntB;
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
} ;
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
BOOST_IS_ABSTRACT(ClassA)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
class ClassB: public ClassA
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
public :
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
int mIntB;
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
virtual void someMethod() {}
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
template < class Archive >
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
void serialize(Archive & ar, const unsigned int /* file_version */ )
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
ar & boost::serialization::base_object < ClassA > ( * this );
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
ar & mIntB;
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
} ;
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
BOOST_CLASS_EXPORT(ClassB)
纯虚类后加上BOOST_ISABSTRACT,而可能会被串行化到的子类用BOOST_CLASS_EXPORT,这样就可以在任何地方串行化 ClassA* 的成员变量。
子类的serialize函数里必须要照顾到基类的成员。
版本控制
在serialize函数中的version参数就是用于版本控制的,所有类的版本号默认为0,新版本的类可以自己指定版本号以便与旧版本相区别。如下
BOOST_CLASS_VERSION(ClassA, 1)
对于save过程,版本号始终为新的,而load过程取决于文件中保存的值,对于新版本新增变量的情况可以这样解决
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
// old definition
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
class ClassA
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
public :
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
int mInt;
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
} ;
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
// new definition
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
class ClassA
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
public :
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
int mInt;
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
int mIntNew;
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
template < class Archive >
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
void serialize(Archive & ar, const unsigned int ver)
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
ar & mInt;
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
if (ver == 1 )
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
ar & mIntB;
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
} ;
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
BOOST_CLASS_VERSION(ClassA, 1 )
对于有改动的情形,稍微复杂一点,可以这样
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
// old definition
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
class ClassA
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
public :
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
TypeA mVarA;
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
} ;
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
// new definition
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
class ClassA
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
public :
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
// suppose now we use B and C instead of A
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
TypeB mVarB;
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
TypeC mVarC;
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
template < class Archive >
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
void serialize(Archive & ar, const unsigned int ver)
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
if (ver < 1 )
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
// here must be loading
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
TypeA varA;
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
ar & varA;
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
// now derive mVarB & mVarC from varA;
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
else
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
ar & mVarB;
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
ar & mVarC;
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
} ;
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
BOOST_CLASS_VERSION(ClassA, 1 )
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
相关文章推荐
- Boost::Serialization试用手记
- Boost::Serialization试用手记
- BOOST 1.33.0 Regex试用手记
- EqualLogic PS5000试用手记之五:小试牛刀
- EqualLogic PS5000试用手记之七:ESXi虚拟机备份 推荐
- EqualLoigc PS5000试用手记之九:容量扩展,冗余,负载平衡的设计
- Visual Basic .NET Power Pack试用手记
- Compellent试用手记之一:数据是流动着的
- Virtual PC 5.2 试用手记
- IntelliJ IDEA 13试用手记(附详细截图)
- 试用Windows Embedded 6.0 R3开发手记
- 技术粗糙,效果不错:广告主眼中的微博商业化-微博粉丝通广告试用手记
- Microsoft Tag试用手记
- debian试用手记
- Spire.XLS试用手记
- Delphi2006试用手记
- Google Writely试用手记(一)
- 试用Windows Vista Build 5600 手记(图)
- boost::serialization学习笔记
- C++,Boost,Serialization