zoukankan      html  css  js  c++  java
  • 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。

















  • 相关阅读:
    安装activeMQ(解压版)
    java匿名发送邮件(不需要登录)
    poi excel导入整数数字自动加小数点解决
    读取excel表中的数据
    DES加密解密实现
    验证码实现(google)
    下载文件到电脑本地
    Properties条件查询(适用于StorageAPI操作数据库)
    java位运算
    python测试开发工具库汇总(转载)
  • 原文地址:https://www.cnblogs.com/blfbuaa/p/7041135.html
Copyright © 2011-2022 走看看