首页 > 代码库 > boost::serialization 拆分serialize函数
boost::serialization 拆分serialize函数
在前篇
boost::serialization 用基类指针转存派生类(错误多多,一波三折)文中我们都是使用serialize函数来实现序列化,其代码格式如下:
private:
friend class boost::serialization::access;
template<typename Archive>
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<typename Archive>
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<typename Archive>
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<class Archive> void serialize( Archive &ar, const unsigned int file_version ){ boost::serialization::split_member(ar, *this, file_version); }
就是调用一个split_member函数,这个函数在头文件split_member.hpp中:
template<class Archive, class T>
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<detail::member_saver<Archive, T> >,
mpl::identity<detail::member_loader<Archive, T> >
>::type typex;//#1
typex::invoke(ar, t, file_version);
}
#1使用traits技术推导出type类型,实际上这个type只有两种类型
template<class Archive, class T> struct member_saver;
template<class Archive, class T> struct member_loader;
这两个结构体中都有一个 invoke 函数(在头文件split_member.hpp中),但是
区分别调用类access 的 member_save 和 member_load 。而这两个函数则分别
调用我们自己定义的 save 和 load 函数。这也就是为什么要声明类boost::serialization::access
为友元类的原因:
template<class Archive, class T>
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<typename Archive>
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<typename Archive>
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<typename Archive>
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<typename Archive>
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<typename Archive>
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<typename Archive>
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了。
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。