用基类的指针去转存派生类时除了上一篇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. C实现JAVA类似ArrayList的静态链接库

    文件结构: ArrayList.h:头文件 ArrayList.c:实现头文件中的功能 ArrayListTest.c:测试 ArrayList.h 头文件的基本框架: #ifndef _ARRAYL ...

  2. python基础5(文件操作,with语句)

    打开文件 #使用 open f = open('路径',mode = '打开模式', encoding='编码') #可以使用with语句打开,不需要关闭,可以同时打开多个文件 with open(' ...

  3. Qt之字典划词

    简述 相信大家都用过词典吧!因为英语不太好...O(∩_∩)O~,所以经常进行划词翻译! 简述 实现 效果 源码 更多参考 实现 原理:鼠标移至某单词之上,获取鼠标位置,然后在对应位置进行取词,翻译! ...

  4. Cannot set web app root system property when WAR file is not expanded

    Cannot set web app root system property when WAR file is not expanded 在tomcat下面可以,在weblogic下面不行的处理方法 ...

  5. select多选 multiple的使用

    select多选  multiple的使用 <html> <head> <script type="text/javascript"> func ...

  6. 【POJ 2750】 Potted Flower(线段树套dp)

    [POJ 2750] Potted Flower(线段树套dp) Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 4566   ...

  7. 深入理解cookie与session

    cookie和session是web开发比較基础也比較重要的知识,cookie和session用于用户的状态管理.简单的来说它们都仅仅是http中的一个配置项,在Servlet规范中也仅仅相应一个类而 ...

  8. 32.智能指针auto_ptr

    #include <iostream> #include <memory> #include <string> #include <vector> us ...

  9. 范型在java中的应用

    根据泛型在java中的不同位置,大致可以分为类泛型.方法泛型和接口泛型.以下三个Demo基本展现三种泛型的用法,其中接口泛型又分两种情况描述.类泛型和方法泛型 import java.util.Arr ...

  10. Unity3D 之 C# 脚本

    引用类型 :class ,interface, 数组 , delegate , object ,string (object 是C#中所有类型,包括所有的值类型和引用类型的根类,string 类型是一 ...