用基类的指针去转存派生类时除了上一篇boost::serialization
用基类指针转存派生类(错误多多,一波三折)
之外。还有还有一种更简单的方法:

用BOOST_CLASS_EXPORT宏。

以下我们来分析如何用BOOST_CLASS_EXPORT来实现

用基类的指针去转存派生类。

首先来看前面实例的一段代码:

void save()
{
std::ofstream ofs("t7.xml");
boost::archive::xml_oarchive oa(ofs);
student_info* sdinfo = new middle_student("wyp", "0099", "1", 15);
oa << BOOST_SERIALIZATION_NVP(sdinfo);//#1
delete sdinfo;
}

当程序运行到#1时就会抛出异常:boost::archive::archive_exception at memory location 0x0017eb30...

boost文档解释是派生类没有实例化(这里是个人理解。。

。“实例化”究竟什么意思也不太理解。。。)。

当我们在#1前面加上注冊的代码时

oa.template register_type<middle_student>(NULL);

实际上就相当于“实例化”。看看register_type的实现代码:

 template<class T>
const basic_pointer_oserializer *
register_type(const T * = NULL){
const basic_pointer_oserializer & bpos =
boost::serialization::singleton<
pointer_oserializer<Archive, T>
>::get_const_instance();
this->This()->register_basic_serializer(bpos.get_basic_serializer());
return & bpos;
}

代码大概就是用单件模式申请一个对象的const指针,预计这个实例化就是为T申请内存。

然后看看BOOST_CLASS_EXPORT宏

#define BOOST_CLASS_EXPORT(T)                   \
BOOST_CLASS_EXPORT_GUID( \
T, \
BOOST_PP_STRINGIZE(T) \
) \

实际上是BOOST_CLASS_EXPORT_GUID宏的定义。继续看看这个宏

#define BOOST_CLASS_EXPORT_GUID(T, K)                                  \
BOOST_CLASS_EXPORT_KEY2(T, K) \
BOOST_CLASS_EXPORT_IMPLEMENT(T) \

原来这个宏展开式两个宏的定义。先看BOOST_CLASS_EXPORT_KEY2(T,K)这个宏

#define BOOST_CLASS_EXPORT_KEY2(T, K)          \
namespace boost { \
namespace serialization { \
template<> \
struct guid_defined< T > : boost::mpl::true_ {}; \
template<> \
inline const char * guid< T >(){ \
return K; \
} \
} /* serialization */ \
} /* boost */ \

这个宏实际上做了一件这种事:返回了一个唯一标记T的const char*字符串。

接下看看看BOOST_CLASS_EXPORT_IMPLEMENT(T)这个宏:

#define BOOST_CLASS_EXPORT_IMPLEMENT(T)                      \
namespace boost { \
namespace archive { \
namespace detail { \
namespace extra_detail { \
template<> \
struct init_guid< T > { \
static guid_initializer< T > const & g; \
}; \
guid_initializer< T > const & init_guid< T >::g = \
::boost::serialization::singleton< \
guid_initializer< T > \
>::get_mutable_instance().export_guid(); \
}}}} \

看看这段代码是不是和register_type实现的代码非常类似:用单件模式返回一个指针。

这就验证了“实例化”事实上就是申请T的内存。

至此我们能够看出BOOST_CLASS_EXPORT和register_type具有类似的功能:(boost 文档)

  • Instantiates code which is not otherwise referred to.
  • Associates an external identifier with the class to be serialized. The fact that the class isn't explicitly referred to implies this requirement.
  • 实例化未被引用的代码。
  • 用一个外部的标识符关联被序列化的类。

    其实该类未被显式引用即暗示这一要求。

好。转回来。如今看看详细如何用BOOST_CLASS_EXPORT这个宏来实现

1.基类文件:student_info.h

class student_info
{
public:
student_info() {}
virtual ~student_info() {}
student_info(const std::string& sn, const std::string& snm, const std::string& sg);
virtual void print_info() const;
private:
friend class boost::serialization::access;
template<typename Archive>
void serialize(Archive& ar, const unsigned int version);
private:
std::string name_;
std::string number_;
std::string grade_;
};

2派生类文件middle_student.h

class middle_student : public student_info
{
public:
middle_student() {}
virtual ~middle_student() {}
middle_student(const std::string& sn, const std::string& snm, const std::string& sg, int age);
virtual void print_info();
private:
friend class boost::serialization::access;
template<typename Archive>
void serialize(Archive& ar, const unsigned int version);
private:
int age_;
};

3.main.cpp

#include <fstream>
#include <boost\archive\text_iarchive.hpp>
#include <boost\archive\text_oarchive.hpp>
#include <boost\serialization\export.hpp> #include "student_info.h" #include "middle_student.h"
BOOST_CLASS_EXPORT(middle_student)
//#1
//#2 void save()
{
std::ofstream ofs("t7.xml");
boost::archive::xml_oarchive oa(ofs);
student_info* sdinfo = new middle_student("wyp", "0099", "1", 15);
oa << BOOST_SERIALIZATION_NVP(sdinfo);
delete sdinfo;
}
void load()
{
std::ifstream ifs("t7.xml");
boost::archive::xml_iarchive ia(ifs);
student_info* sdinfo = NULL;
ia >> BOOST_SERIALIZATION_NVP(sdinfo);
middle_student* mds = dynamic_cast<middle_student*>(sdinfo);
mds->print_info();
} int main()
{
save();
load();
return 0;
}

看见红色字体的两行没有,就是这样用BOOST_CLASS_EXPORT宏,这样就不用注冊派生类。

假如又有一个student_info的派生类xxx_student,且头文件为"xxx_student.h",你仅仅须要

在#1加入#include "xxx_student.h"

在#2加入BOOST_CLASS_EXPORT(xxx_student)

这样你就也能使用基类student_info的指针来转存派生了xxx_student。

BOOST_CLASS_EXPORT的更多相关文章

  1. 【boost】使用serialization库序列化子类

    boost.serialization库是一个非常强大又易用的序列化库,用于对象的保存与持久化等. 使用base_object可以在序列化子类的同时也序列化父类,以此获得足够的信息来从文件或网络数据中 ...

  2. boost serialization

    Archive An archive is a sequence of bytes that represented serialized C++ objects. Objects can be ad ...

随机推荐

  1. python自动化报错

    今天使用python.然而遇见了报错.抓狂的一笔.有说path写错的,有说是...网上查到的资料也是很少.后来突然发现,页面上我暂时能看到的元素可以定位并进行操作.看不到的无法进行...ps此时我没有 ...

  2. BZOJ 5104 Fib数列(二次剩余+BSGS)

    斐波那契数列的通项: \[\frac{1}{\sqrt{5}}((\frac{1+\sqrt{5}}{2})-(\frac{1-\sqrt{5}}{2}))\] 设T=\(\sqrt{5}*N\),\ ...

  3. FastDFS图片服务器搭建

    *FastDFS图片服务器搭建准备:1.需要libfastcommon安装包 选择最新稳定版(libfastcommon-1.0.36.tar.gz)2.需要FastDFS安装包 选择最新稳定版(fa ...

  4. Object-C,NSArraySortTest,数组排序3种方式

    晚上回来,继续写Object-C的例子,今天不打算写iOS可视化界面的程序,太累了. 刚刚dady又电话过来,老一套,烦死了. 其实,我一直一个观点,无论发生什么事情,不要整天一副不开心的样子. 开开 ...

  5. Effective C++ 11-17

    11.为须要动态分配内存的类声明一个拷贝构造函数和一个赋值操作符. 显然,由于动态内存分配,绝对会有深浅拷贝的问题,要重写拷贝构造函数.使其为深拷贝,才干实现真正意义上的拷贝.这是我理解的关于要声明拷 ...

  6. hadoop1.1.0的伪分布搭建步骤

    watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvbWFuYnVyZW4wMQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQk ...

  7. C++归并排序总结

    #include <iostream> using namespace std; //归并排序非递归版. void Sort(int a[], int n,int high) { int ...

  8. 一次误报引发的DNS检测方案的思考:DNS隧道检测平民解决方案

    摘自:http://www.freebuf.com/articles/network/149328.html 通过以上分析得出监控需要关注的几个要素:长域名.频率.txt类型.终端是否对解析ip发起访 ...

  9. rest_framework 解析器(下 全局配置使用)

    解析器 一般都是全局设置 参考文档 www.cnblogs.com/wupeiqi/articles/.html REST_FRAMEWORK=( "DEFAULT_PARSER_CLASS ...

  10. 提高realm存储速率

    我的数据量大约有2.5M,但是完全存储到数据库差不多用了11秒,有没有比较好的方法提高存储效率 提高realm存储速率 >> android这个答案描述的挺清楚的:http://www.g ...