在
怎样用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...
};
按照前面几篇的列子:
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 是一个模板派生类
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:\sdk\boost_1_53_0\boost\serialization\access.hpp 118
Error 2 error C2248: ‘T88::divided_class<T>::serialize‘ : cannot access private member declared in class ‘T88::divided_class<T>‘ d:\sdk\boost_1_53_0\boost\serialization\access.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:\sdk\boost_1_53_0\boost\serialization\access.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 ...
}//求大神解决问题。。。。
怎样用boost::serialization去序列化派生模板类(续)
时间: 2024-10-14 04:24:05