如何用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 void serialize(Archive & ar, const unsigned int file_version)//#2

 在

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

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

基类代码:

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 ...
}//求大神解决这个问题。。。。