程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> boost::serialization 拆分serialize函數

boost::serialization 拆分serialize函數

編輯:C++入門知識

在前篇

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::eval_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 number_;
	std::string grade_;
};
這個函數是intrusive的,我們也可以用一種non-intrusive:

class student_info
{
public:
	//...
private:
	template
	friend void serialize(Archive& ar, student_info &sdinfo, const unsigned int file_version);
private:
	std::string name_;
	std::string number_;
	std::string grade_;
};
再類外面實現 serialize 函數:

template
void serialize(Archive& ar, student_info &sdinfo, const unsigned int file_version)
{
	ar & BOOST_SERIALIZATION_NVP(sdinfo.name_);
	ar & BOOST_SERIALIZATION_NVP(sdinfo.number_);
	ar & BOOST_SERIALIZATION_NVP(sdinfo.grade_);
}
這樣就ok了。











  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved