BOOST_CLASS_EXPORT

用基类的指针去转存派生类时除了上一篇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 <boostarchive	ext_iarchive.hpp>
#include <boostarchive	ext_oarchive.hpp>
#include <boostserializationexport.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。

















原文地址:https://www.cnblogs.com/blfbuaa/p/7041135.html