序列化(serializtion)是指把对象信息转换成可以存储或者通过网络连接传输格式的过程,然后在本地或者在另一个计算机环境中可以重构出原有的对象信息是指反序列化。

前言

本文只介绍通过boost serialization存储的优势,先通过例子简单明白。假如现在你是一个学校学生系统管理员,你需要保存学生信息,比如学生学好,名字,年龄。当然最简单的方式是通过C++的文本操作解决方案。

//***********************************************************
//FUNCTION::
void CStudentInfoUtility::writeStudentInfo(const std::string vFileName, const CStudent* vStudent) const
{_ASSERT(!vFileName.empty() && vStudent);std::ofstream FileOut;FileOut.open(vFileName, std::ios::binary);_HIVE_EARLY_EXIT(FileOut.fail(), "File open fail");FileOut << vStudent->getStudentId() << " ";FileOut << vStudent->getStudentName() << " ";FileOut << vStudent->getStudentAge() << std::endl;FileOut.close();
}//***********************************************************
//FUNCTION::
void CStudentInfoUtility::readStudentInfo(const std::string vFileName, CStudent* vStudent) const
{_ASSERT(!vFileName.empty() && vStudent);std::ifstream FileIn;FileIn.open(vFileName, std::ios::binary);_HIVE_EARLY_EXIT(FileIn.fail(), "File open fail");int StudentId = 0, Age = 0;std::string Name;FileIn >> StudentId;FileIn >> Name;FileIn >> Age;vStudent->setStudentId(StudentId);vStudent->setStudentName(Name);vStudent->setStudentAge(Age);FileIn.close();
}

这样可以满足需求,但是如果现在需要添加学生新的信息,那么我需要改动上面的代码,这违背了面向对象的开闭原则,而且最重要的是上面的操作非常繁琐,都需要自己自定义去写和读相应属性操作。然而boost serialization很好的帮我们做了这些工作,它的优势是简单和高效,下面我依次介绍boost serialization的用法。

Boost Serialization Classification

Boost serialization分为两类,一个是侵入式(Intrusive),即嵌入代码到类中。

class CPerson
{
public:CPerson(void);CPerson(const std::string& vName, unsigned int vAge);virtual ~CPerson(void);const std::string& getName() const {return m_Name;}int                getAge()  const {return m_Age;}private:std::string m_Name;unsigned int m_Age;friend class boost::serialization::access;template<class Archive>void serialize(Archive& ar, const unsigned int version){ar & m_Name;ar & m_Age;}
};

第二类是非侵入式,它的特点是没有暴露类的定义,不过需要暴露类的成员变量,即private需要改动未public,因为boost::serialization需要访问成员变量,所以需要暴露。但是我不建议这种写法,违背了面向对象的封装。

class CNonIntrusive
{
public:CNonIntrusive(void);CNonIntrusive(const std::string& vName, unsigned int vAge);virtual ~CNonIntrusive(void);const std::string& getName() const {return m_Name;}int                getAge()  const {return m_Age;}std::string m_Name;unsigned int m_Age;
};namespace boost {namespace serialization {template<class Archive>void serialize(Archive & ar, CNonIntrusive & g, const unsigned int version){ar & g.m_Name;ar & g.m_Age;}}
} 

Serializable Members

序列化成员变量,如同上面侵入式的代码,不过首先需要加上头文件#include <boost/serialization/serialization.hpp> 类中写法如侵入式代码。


在成员变量下声明了友元类access,表示可以访问到CPerson这个类的私有变量,接着下部有个模板函数serialize 其中的Archive& ar可以对成员变量进行序列化和反序列,当序列化的时候,&表示 <<。而反序列化的时候就表示 >>。


这里使用的是二进制的文档序列化,OS当成OA构造函数形参传入, OA << Person1 会调用刚刚的模板函数serialize,然后模板函数会把成员变量值传入OA中的OS中。

Derived Classes

序列化子类,只需要在子类加上ar & boost::serialization::base_object<CPerson>(*this); 表示会调用父类的serialize序列化父类的成员变量。

#pragma once
#include "person.h"
#include <boost/serialization/export.hpp>class CPersonChild : public CPerson
{
public:CPersonChild(void);CPersonChild(const std::string& vName, unsigned int vAge, unsigned int vChildTag);virtual ~CPersonChild(void);unsigned int getChildTag() const {return m_ChildTag;}private:unsigned int m_ChildTag;friend boost::serialization::access;template<class Archive>void serialize(Archive& ar, const unsigned int version){ar & boost::serialization::base_object<CPerson>(*this);ar & m_ChildTag;}
};

Pointers

其中需要注意的是在反序列化的时候CStudent* pSecondStudent = nullptr; 这里不能new一个对象,需要赋空值,因为boost::serialize模板函数会判断是否存在当前对象,如果没有它会创建一个对象,而如果你new了一个对象,就存在两个对象,就会存在内存泄漏。

Arrays

STL Collections

注意序列化stl 容器需要包含相应的头文件,这里是vector,所以头文件是#include <boost/serialization/vector.hpp>

Class Versioning

void serialize(Archive& ar, const unsigned int version) 刚刚没说第二个形参的作用,它表示的是版本号,默认是0。我们可以手动设置当前类对象序列的版本号来控制序列化相应属性。比如,你以前序列化了一个类,现在这个类加了新属性,那么反序列以前的文档肯定出错,因为文档内容是没有相应的新属性,所以可以使用后面的version来控制是否反序列化。

#pragma once
#include <string>
#include <boost/serialization/serialization.hpp>
#include <boost/serialization/version.hpp>class CVersion
{
public:CVersion(void);CVersion(const std::string& vName, unsigned int vAge);virtual ~CVersion(void);const std::string& getName() const {return m_Name;}int                getAge()  const {return m_Age;}private:unsigned int m_Age;std::string m_Name;friend class boost::serialization::access;template <class Archive> friend void serialize(Archive &ar, CVersion &v, const unsigned int version); //template<class Archive>//void serialize(Archive& ar, const unsigned int version)//{//  ar & m_Age;//  if (version > 0)//      ar & m_Name;//}
};BOOST_CLASS_VERSION(CVersion, 1)template <typename Archive>
void serialize(Archive &ar, CVersion& v, const unsigned int version)
{ar & v.m_Age; if (version > 0) ar & v.m_Name;
}

BOOST_CLASS_VERSION(CVersion, 1) 表示当前序列化的版本是1,从而也序列化名字。

Polymorphism

面向对象的第三大特性多态是否也支持呢。答案是肯定的,而且有两种方式支持多态。

  1. export
    头文件 #include <boost/serialization/export.hpp>
//BOOST_CLASS_EXPORT(CPersonChild)
BOOST_CLASS_EXPORT(CPersonChild, "CPersonChild")
//***********************************************************
//FUNCTION::
void testPolymorphism()
{std::ofstream FileOut("archive.txt");boost::archive::text_oarchive OA(FileOut);CPerson* pPerson = new CPersonChild("Polymorphism", 10, 1);OA << pPerson;FileOut.close();delete pPerson;CPerson* pPerson2 = nullptr;std::ifstream FileIn("archive.txt");boost::archive::text_iarchive IA(FileIn);IA >> pPerson2;CPersonChild* pPerson3 = dynamic_cast<CPersonChild*>(pPerson2);std::cout << pPerson3->getName() << " " << pPerson3->getAge() << " " << pPerson3->getChildTag() << std::endl;
}

BOOST_CLASS_EXPORT(CPersonChild, "CPersonChild") 注意这个标签,相当于给派生类指定一个key,不过直接使用BOOST_CLASS_EXPORT(CPersonChild) 也是可以的,都能找到相应的派生类。

  1. registration
//***********************************************************
//FUNCTION::
void testPolymorphism2()
{std::ofstream FileOut("archive.txt");boost::archive::text_oarchive OA(FileOut);OA.register_type<CPersonChild>();CPerson* pPerson = new CPersonChild("Polymorphism 2", 10, 1);OA << pPerson;FileOut.close();delete pPerson;CPerson* pPerson2 = nullptr;std::ifstream FileIn("archive.txt");boost::archive::text_iarchive IA(FileIn);IA.register_type<CPersonChild>();IA >> pPerson2;CPersonChild* pPerson3 = dynamic_cast<CPersonChild*>(pPerson2);std::cout << pPerson3->getName() << " " << pPerson3->getAge() << " " << pPerson3->getChildTag() << std::endl;
}

OA.register_type<CPersonChild>(); 注册了派生类的信息,所以也能根据相应的子类进行序列化和反序列化。

Splitting serialize into save/load

上面的序列化和反序列化都是通过一个模板函数serialize函数,其实这个函数可以拆分,这样在特定的场景也能功能明确。比如刚刚的版本控制,也能通过拆分函数来完成。

#pragma once
#include "Person.h"
#include <boost/serialization/list.hpp>
#include <boost/serialization/version.hpp>
#include <boost/serialization/split_member.hpp>class CSplitting
{
public:CSplitting(void){}CSplitting (const std::string& vName) : m_SplittingName(vName){}~CSplitting (void);void addPerson(CPerson* vPerson) {_ASSERT(vPerson); m_PersonList.push_back(vPerson);}void displayInfo();private:std::string m_SplittingName;std::list<CPerson*> m_PersonList;friend class boost::serialization::access;template<class Archive>void save(Archive & ar, const unsigned int version) const{ar  & m_SplittingName;ar  & m_PersonList;}template<class Archive>void load(Archive & ar, const unsigned int version){if(version > 0)ar & m_SplittingName;ar  & m_PersonList;}BOOST_SERIALIZATION_SPLIT_MEMBER()
};BOOST_CLASS_VERSION(CSplitting, 1)

序列化调用save函数,反序列化调用load函数。注意类中需要加入一个重要的宏,BOOST_SERIALIZATION_SPLIT_MEMBER

【参考资料】
【1】http://blog.csdn.net/zj510/article/details/8105408
【2】http://zh.highscore.de/cpp/boost/serialization.html
【3】http://www.ibm.com/developerworks/cn/aix/library/au-boostserialization/index.html
【4】 http://www.boost.org/doc/libs/1_51_0/libs/serialization/doc/index.html

Boost serialization相关推荐

  1. boost::serialization模块测试extended_type_info的实现,使用多个共享库时有效

    boost::serialization模块测试extended_type_info的实现,使用多个共享库时有效 实现功能 C++实现代码 实现功能 boost::serialization模块测试e ...

  2. boost::serialization模块实现测试 shared_ptr 序列化的测试程序

    boost::serialization模块实现测试 shared_ptr 序列化的测试程序 实现功能 C++实现代码 实现功能 boost::serialization模块实现测试 shared_p ...

  3. boost::serialization模块实现快速二进制归档的测试程序

    boost::serialization模块实现快速二进制归档的测试程序 实现功能 C++实现代码 实现功能 boost::serialization模块实现快速二进制归档的测试程序 C++实现代码 ...

  4. boost::serialization模块指针反序列化的安全异常处理示例

    boost::serialization模块指针反序列化的安全异常处理示例 实现功能 C++实现代码 实现功能 boost::serialization模块指针反序列化的安全异常处理示例 C++实现代 ...

  5. boost::serialization模块测试 auto_ptr 序列化的测试程序

    boost::serialization模块测试 auto_ptr 序列化的测试程序 实现功能 C++实现代码 实现功能 boost::serialization模块测试 auto_ptr 序列化的测 ...

  6. boost::serialization相关的测试程序

    boost::serialization相关的测试程序 实现功能 C++实现代码 实现功能 boost::serialization相关的测试程序 C++实现代码 #include <boost ...

  7. 最常用的两种C++序列化方案的使用心得(protobuf和boost serialization)

    From: http://www.cnblogs.com/lanxuezaipiao/p/3703988.html 导读 1. 什么是序列化? 2. 为什么要序列化?好处在哪里? 3. C++对象序列 ...

  8. boost::serialization模块extended_type_info_typeid测试程序

    boost::serialization模块extended_type_info_typeid测试程序 实现功能 C++实现代码 实现功能 boost::serialization模块extended ...

  9. Boost Serialization 库(一个有效的调试工具)

    使用了 Boost Serialization 的 Hello World 在执行更重要的任务之前,我们先来验证一下概念.在以下的 清单 1 中,您会看到一个字符串,它的值被转储到一个归档文件中.在以 ...

  10. 畅游C++ Boost Serialization 序列化

    原文链接:https://blog.csdn.net/qq2399431200/article/details/45621921 目录 1.工作环境 2.使用方法 3.工程下载 4.总结 5.参考文献 ...

最新文章

  1. 伍六七带你学算法 入门篇-最长回文串
  2. 记selenium1.0升级到selenium2.0
  3. 分享代码到GitHub
  4. FreeWheel基于Go的实践经验漫谈——GC是大坑(关键业务场景不用),web框架尚未统一,和c++性能相比难说...
  5. 最优化方法外罚函数法Matlab,最优化方法 第三篇(罚函数法).pdf
  6. Ubuntu11.04更新源(转)
  7. RTL8111H-CG规格书 DATASHEET
  8. Django:快速搭建简单的Blog
  9. 作者:江荣(1984-),男,博士,国防科学技术大学助理研究员。
  10. [VJ][bfs]Catch That Cow
  11. 三届格莱美奖得主Ryan Tedder将在Origin上发行NFT
  12. 2000年一元钱牡丹图案现在值钱吗?
  13. Remap 后的 USART1 不能发送数据
  14. image 第二次使用就出错是怎么回事_第二次上机报告-RNA-seq (HISAT - SAMtools- StringTie - ballgown)amp;amp;Gene-Assembly
  15. JavaSE基础笔记一
  16. Linux学习笔记2 - 字符界面
  17. 凸优化有关的数值线性代数知识 3LU Cholesky和LDL因式分解
  18. c语言c99和c90,C89 / C90,C99和C11的兼容性
  19. 餐饮企业免费申请点餐小程序
  20. 您必须拥有这台计算机上的终端服务器用户访问权限的解决方案

热门文章

  1. 【python】db.Column(db.Integer, primary_key=True, autoincrement=True)
  2. 王琪你计算机学院,麦考瑞大学 AI 实验室中科院信工所,两场论文直播重磅来袭!...
  3. [Lua基础]操作系统库——Date,Time,Clock
  4. MacBook上有哪些相见恨晚的神器
  5. Wireshark实验
  6. 嵌入式Linux资源网站,嵌入式Linux名词及资源
  7. 2022吴恩达机器学习第二周
  8. python的学习笔记案例1--汇率兑换5.0
  9. leetcode:数组:1467自矩形查询
  10. UI——无限轮播图和分栏控制器