boost::serialization 拆分serialize函数(一)

2014-11-24 12:30:38 · 作者: · 浏览: 0
在前篇

boost::serialization 用基类指针转存派生类(错误多多,一波三折)文中我们都是使用serialize函数来实现序列化,其代码格式如下:

private:
	friend class boost::serialization::access;
	template
   
    
	void serialize(Archive& ar, const unsigned int version)
	{
		ar & BOOST_SERIALIZATION_NVP(name_);
		ar & BOOST_SERIALIZATION_VP(number_);
		ar & BOOST_SERIALIZATION_NVP(grade_);
	}
   
其实这个函数相当于两个函数:但我们使用xxx_oarchive时它等价于把对象数据save到文档中,
当我们使用xxx_iachive时它等价于把数据从文档中load给对象数据。因此可以它拆分成两个函数
save 和 load 函数。还用前面的例子。
save函数:

template
   
    
void save(Archive& ar, const unsigned int version) const
{
	ar << BOOST_SERIALIZATION_NVP(name_);
	ar << BOOST_SERIALIZATION_NVP(number_);
	ar << BOOST_SERIALIZATION_NVP(grade_);
}
   
load函数:

template
   
    
void load(Archive& ar, const unsigned int version)
{
	ar >> BOOST_SERIALIZATION_NVP(name_);
	ar >> BOOST_SERIALIZATION_NVP(number_);
	ar >> BOOST_SERIALIZATION_NVP(grade_);
}
   
最后需要加上一个宏:

BOOST_SERIALIZATION_SPLIT_MEMBER() //must be part of class
这个宏必须是在类的内部。其实这个宏实现了一个模版函数:

#define BOOST_SERIALIZATION_SPLIT_MEMBER()                       \
	template
   
                                              \
	void serialize(                                                  \
	Archive &ar,                                                 \
	const unsigned int file_version                              \
	){                                                               \
	boost::serialization::split_member(ar, *this, file_version); \
} 
   
就是调用一个split_member函数,这个函数在头文件split_member.hpp中:

template
   
    
inline void split_member(
		 Archive & ar, T & t, const unsigned int file_version
		)
{
	typedef BOOST_DEDUCED_TYPENAME mpl::eva l_if<
		BOOST_DEDUCED_TYPENAME Archive::is_saving,
		mpl::identity
    
      >, mpl::identity
     
       > >::type typex;//#1 typex::invoke(ar, t, file_version); }
     
    
   
#1使用traits技术推导出type类型,实际上这个type只有两种类型
template struct member_saver;
template struct member_loader;
这两个结构体中都有一个 invoke 函数(在头文件split_member.hpp中),但是
区分别调用类access 的 member_save 和 member_load 。而这两个函数则分别
调用我们自己定义的 save 和 load 函数。这也就是为什么要声明类boost::serialization::access
为友元类的原因:

template
   
    
static void member_save(Archive & ar, 
						//const T & t,
						T & t,
						const unsigned int file_version
						)
{
	t.save(ar, file_version);//access类成员函数member_save,由此可见boost设计模式很复杂,但是值得学习
}
friend class boost::serialization::access;
//我们的save和load代码
   
这样access就可以调用我们写的save和load代码了。
好了现在来看完整代码吧:

class student_info
{
public:
	student_info() {}
	virtual ~student_info() {}
	student_info(const std::string& sn, const std::string& snm, const std::string& sg, const std::string& cs)
		: name_(sn), number_(snm), grade_(sg), class_(cs)
	{
	}

	virtual void print_info() const
	{
		std::cout << name_ << " " << number_ << " " << grade_ << " " << class_ << " ";
	}

private:
	//friend class boost::serialization::access;
	/*
	template
   
    
	void serialize(Archive& ar, const unsigned int version)
	{
		ar & BOOST_SERIALIZATION_NVP(name_);
		ar & BOOST_SERIALIZATION_VP(number_);
		ar & BOOST_SERIALIZATION_NVP(grade_);
	}
    */
    friend class boost::serialization::access;//友元类这样它的成员函数member_save(load)就可以调用我们自己实现的save、load
	template
    
      void save(Archive& ar, const unsigned int version) const { ar << BOOST_SERIALIZATION_NVP(name_); ar << BOOST_SERIALIZATION_NVP(number_); ar << BOOST_SERIALIZATION_NVP(grade_); ar << BOOST_SERIALIZATION_NVP(class_); } template
     
       void load(Archive& ar, const unsigned int version) { ar >> BOOST_SERIALIZATION_NVP(name_); ar >> BOOST_SERIALIZATION_NVP(number_); ar >> BOOST_SERIALIZATION_NVP(grade_); } BOOST_SERIALIZATION_SPLIT_MEMBER() //must be part of class private: std::string name_; std::string number_; std::string grade_; };
     
    
   



接下来看一看以前前面的文章有个遗留的问题,就是那个serialize函数:

class student_info
{
public:
	//...
private:
	friend class boost::serialization::access;
	template
   
    
	void serialize(Archive& ar, const unsigned int version)
	{
	ar & BOOST_SERIALIZATION_NVP(name_);
	ar & BOOST_SERIALIZATION_VP(number_);
	ar & BOOST_SERIALIZATION_NVP(grade_);
	}
	
private:
	std::string name_;
	std::string numb