• 如何用boost::serialization去序列化派生模板类(续)


     在

    如何用boost::serialization去序列化派生模板类这篇文章中,介绍了序列化派生类模板类,

    在写測试用例时一直出现编译错误,调了非常久也没跳出来,今天偶然试了一下...竟然调了出来。

    先看看变异错误的代码(。。。看不出有错,但是编译就有错)。

    基类代码:

    class base_class
    {
    public:
    	base_class(int m=0) : base_member_(0) {}
    	virtual ~base_class() {}
    
    	virtual void print_data() = 0;
    
    private:
    	class boost::serialization::access;//#1
    	template<typename Archive>
    	void serialize(Archive & ar, const unsigned int file_version)//#2
    	{
    		ar & BOOST_SERIALIZATION_NVP(base_member_);
    		//ar & BOOST_SERIALIZATION_NVP(other member...);
    	}
    
    protected:
    	int base_member_;
    	//other member...
    };

    
    依照前面几篇的列子:
    
    
    

    #1应该声明为友元类(不知道为什么,看看这篇文章boost::serialization 拆分serialize函数)。

    #2实现一个serialize函数。这应该没问题???????但是却又问题。后面就知

    道了。

    然后来看看派生模板类的代码:

    template<typename T>//#1
    class divided_class : public base_class
    {
    public:
    	divided_class(int m = 0, T d = T()) : base_class(m), diveded_member_(d) {}
    	virtual ~divided_class() {}
    
    	virtual void print_data()
    	{
    		std::cout << base_member_ << " "
    			<< diveded_member_ << " ";
    	}
    
    private:
    	class boost::serialization::access;//#2
    	template<typename Archive>
    	void serialize(Archive& ar, const unsigned int file_version)//#3
    	{
    		ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(base_class);
    		ar & BOOST_SERIALIZATION_NVP(diveded_member_);
    		//ar & BOOST_SERIALIZATION_NVP(other member...);
    	}
    
    private:
    	T diveded_member_;
    	//other member....
    };

    
    #1 diveide_class 是一个模板派生类
    
    
    

    #2 声明友元类

    #3 实现派生类的serialize函数

    这样写应该也没问题。

    好,接下来写个save()函数測试一下:

    void save()
    {
    	std::ofstream ofs("t8.xml");
    	boost::archive::xml_oarchive oa(ofs);
    
    	base_class* int_base = new divided_class<int>(1, 3);
    	base_class* str_base = new divided_class<std::string>(1, "wyp");
    	base_class* float_base = new divided_class<float>(1, 3.1415926f);
    
    	//Now the tricky point is to register class in serialize
    	oa.template register_type<divided_class<int>>(NULL);
    	oa.template register_type<divided_class<std::string>>(NULL);
    	oa.template register_type<divided_class<float>>(NULL);
    
    	//begin serialize
    	oa & BOOST_SERIALIZATION_NVP(int_base);
    	oa & BOOST_SERIALIZATION_NVP(str_base);
    	oa & BOOST_SERIALIZATION_NVP(float_base);
    
    	//delete pointer ...
    }
    在main函数中条用这个save函数。

    编译器会出现几个错误:

    Error	1	error C2248: 'T88::divided_class<T>::serialize' : cannot access private member declared in class 'T88::divided_class<T>'	d:sdkoost_1_53_0oostserializationaccess.hpp	118
    Error	2	error C2248: 'T88::divided_class<T>::serialize' : cannot access private member declared in class 'T88::divided_class<T>'	d:sdkoost_1_53_0oostserializationaccess.hpp	118
    ...
    就是派生类的serialize不能訪问私有数据。非常诡异!

    serialize本来就是派生类的成员函数,并且access类还声明为友元类(access 要调用派生类的serialize)。不知道为什么?求解。。。。。。。

    找不出就换了一种方法,上面的serialize函数intrusive式,就换成一种non-intrusive式的,

    由于非入侵式的没有this指针:

    template<typename Archive>
    	void serialize(Archive& ar, const unsigned int file_version)
    	{
    		ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(base_class);//#1
    		ar & BOOST_SERIALIZATION_NVP(diveded_member_);
    		//ar & BOOST_SERIALIZATION_NVP(other member...);
    	}
    #1这个宏中包括一个this指针,因此这个仅仅能留在类里面,就是定义一个函数条用这个宏:

    template<typename Archive>
    		void serialize_base_class(Archive& ar)
    		{
    			ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(base_class);
    		}
    然后声明派生模板类的友元函数serialize:

    template<typename Archive, typename TT>
    	                      friend void serialize(Archive& ar, divided_class<TT>& divcls,                                                      const unsigned int file_version);
    接着就是在类的外面实现这个函数:

    template<typename Archive, typename T>
    void serialize(Archive& ar, divided_class<T>& discls, const unsigned int file_version)
    	{
    		discls.serialize_base_class(ar);//条用序列化基类的成员函数
    		ar & BOOST_SERIALIZATION_NVP(discls.diveded_member_);
    		//ar & BOOST_SERIALIZATION_NVP(other member...);
    	}
    这样应该解决这个问题了,编译。。。。

    果然攻克了派生类的问题,但是基类却出现了和派生了一样的问题:

    Error	2	error C2248: 'T88::base_class::serialize' : cannot access private member declared in class 'T88::base_class'	d:sdkoost_1_53_0oostserializationaccess.hpp	118
    
    仅仅能才去相同的方法来解决:

    private:
    		/*
    		class boost::serialization::access;
    		template<typename Archive>
    		void serialize(Archive & ar, const unsigned int file_version)
    		{
    			ar & BOOST_SERIALIZATION_NVP(base_member_);
    			//ar & BOOST_SERIALIZATION_NVP(other member...);
    		}*
    		*/
    template<typename Archive>
    friend void serialize(Archive& ar, base_class& bascls, const unsigned int file_version);
    
    在类外面:
    template<typename Archive>
    	void serialize(Archive& ar, base_class& bascls, const unsigned int file_version)
    	{
    		ar & BOOST_SERIALIZATION_NVP(bascls.base_member_);
    		//ar & BOOST_SERIALIZATION_NVP(other member...);
    	}
    编译执行果然解决这个问题!

    但是如今还是不知道原来的代码有什么错误!

    正确的測试列子代码例如以下:

    class base_class
    {
    public:
    	base_class(int m=0) : base_member_(0) {}
    	virtual ~base_class() {}
    
    	virtual void print_data() = 0;
    
    private:
    	template<typename Archive>
    	friend void serialize(Archive& ar, base_class& bascls, const unsigned int file_version);
    protected:
    	int base_member_;
    	//other member...
    };
    
    template<typename Archive>
    void serialize(Archive& ar, base_class& bascls, const unsigned int file_version)
    {
    	ar & BOOST_SERIALIZATION_NVP(bascls.base_member_);
    	//ar & BOOST_SERIALIZATION_NVP(other member...);
    }
    
    
    template<typename T>
    class divided_class : public base_class
    {
    public:
    	divided_class(int m = 0, T d = T()) : base_class(m), diveded_member_(d) {}
    	virtual ~divided_class() {}
    
    	virtual void print_data()
    	{
    		std::cout << base_member_ << " "
    			<< diveded_member_ << " ";
    	}
    
    private:
    	class boost::serialization::access;
    	template<typename Archive>
    	void serialize_base_class(Archive& ar)
    	{
    		ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(base_class);
    	}
    
    	template<typename Archive, typename TT>
    	friend void serialize(Archive& ar, divided_class<TT>& divcls, const unsigned int file_version);
    
    private:
    	T diveded_member_;
    	//other member....
    };
    
    template<typename Archive, typename T>
    void serialize(Archive& ar, divided_class<T>& discls, const unsigned int file_version)
    {
    	discls.serialize_base_class(ar);
    	ar & BOOST_SERIALIZATION_NVP(discls.diveded_member_);
    	//ar & BOOST_SERIALIZATION_NVP(other member...);
    }
    
    void save()
    {
    	std::ofstream ofs("t8.xml");
    	boost::archive::xml_oarchive oa(ofs);
    
    	base_class* int_base = new divided_class<int>(1, 3);
    	base_class* str_base = new divided_class<std::string>(1, "wyp");
    	base_class* float_base = new divided_class<float>(1, 3.1415926f);
    
    	//Now the tricky point is to register class in serialize
    	oa.template register_type<divided_class<int>>(NULL);
    	oa.template register_type<divided_class<std::string>>(NULL);
    	oa.template register_type<divided_class<float>>(NULL);
    
    	//begin serialize
    	oa & BOOST_SERIALIZATION_NVP(int_base);
    	oa & BOOST_SERIALIZATION_NVP(str_base);
    	oa & BOOST_SERIALIZATION_NVP(float_base);
    
    	//delete pointer ...
    }
    

    错误代码例如以下(有兴趣的调下。。。。error存档):

    class base_class
    {
    public:
    	base_class(int m=0) : base_member_(0) {}
    	virtual ~base_class() {}
    
    	virtual void print_data() = 0;
    
    private:
    	class boost::serialization::access;
    	template<typename Archive>
    	void serialize(Archive & ar, const unsigned int file_version)
    	{
    	ar & BOOST_SERIALIZATION_NVP(base_member_);
    	//ar & BOOST_SERIALIZATION_NVP(other member...);
    	}
    	
    protected:
    	int base_member_;
    	//other member...
    };
    
    template<typename T>
    class divided_class : public base_class
    {
    public:
    	divided_class(int m = 0, T d = T()) : base_class(m), diveded_member_(d) {}
    	virtual ~divided_class() {}
    
    	virtual void print_data()
    	{
    		std::cout << base_member_ << " "
    			<< diveded_member_ << " ";
    	}
    
    private:
    	class boost::serialization::access;
    	template<typename Archive>
    	void serialize(Archive& ar, const unsigned int file_version)
    	{
    	ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(base_class);
    	ar & BOOST_SERIALIZATION_NVP(diveded_member_);
    	//ar & BOOST_SERIALIZATION_NVP(other member...);
    	}
    private:
    	T diveded_member_;
    	//other member....
    };
    
    void save()
    {
    	std::ofstream ofs("t8.xml");
    	boost::archive::xml_oarchive oa(ofs);
    
    	base_class* int_base = new divided_class<int>(1, 3);
    	base_class* str_base = new divided_class<std::string>(1, "wyp");
    	base_class* float_base = new divided_class<float>(1, 3.1415926f);
    
    	//Now the tricky point is to register class in serialize
    	oa.template register_type<divided_class<int>>(NULL);
    	oa.template register_type<divided_class<std::string>>(NULL);
    	oa.template register_type<divided_class<float>>(NULL);
    
    	//begin serialize
    	oa & BOOST_SERIALIZATION_NVP(int_base);
    	oa & BOOST_SERIALIZATION_NVP(str_base);
    	oa & BOOST_SERIALIZATION_NVP(float_base);
    
    	//delete pointer ...
    }//求大神解决这个问题。。。。
















  • 相关阅读:
    ListView添加HeaderView的顺序问题
    shape与selector配合使用实现Tab下划线效果
    在java代码中设置TextView的字体大小,单位设为sp
    一个textView中的文字设置成两种颜色
    Android studio生成类图
    linux常用命令总结
    主机CPU与显卡选择
    电脑与显示器四种接口
    Linux shell
    Linux 常用命令二
  • 原文地址:https://www.cnblogs.com/mfrbuaa/p/3778322.html
Copyright © 2020-2023  润新知