通过基类指针序列化派生类时,我在提升序列化方面遇到了一些问题。我需要一个系统来序列化系统中接收到的一些对象,所以我需要随着时间的推移进行序列化。这不是一个真正的问题,因为我可以boost::archive::binary_oarchive
在需要时打开并序列化对象。很快我注意到 boost 是通过内存地址执行对象跟踪,所以第一个问题是共享相同内存地址的不同对象及时保存为同一个对象。这可以通过在所需的派生类中使用以下宏来解决:
BOOST_CLASS_TRACKING(className, boost::serialization::track_never)
这工作正常,但同样,当基类不是抽象的时,基类没有正确序列化。在以下示例中,基类序列化方法仅对第一个对象调用一次。在下文中,boost 假设该对象之前已经序列化,尽管该对象具有不同的类型。
#include <iostream>
#include <fstream>
#include <boost/serialization/export.hpp>
#include <boost/serialization/base_object.hpp>
#include <boost/serialization/list.hpp>
#include <boost/serialization/map.hpp>
#include <boost/serialization/vector.hpp>
#include <boost/serialization/shared_ptr.hpp>
#include <boost/archive/archive_exception.hpp>
#include <boost/archive/binary_oarchive.hpp>
#include <boost/archive/binary_iarchive.hpp>
using namespace std;
class AClass{
public:
AClass(){}
virtual ~AClass(){}
private:
double a;
double b;
//virtual void virtualMethod() = 0;
private:
friend class boost::serialization::access;
template<class Archive>
void serialize(Archive & ar, const unsigned int version)
{
ar & a;
ar & b;
cout << "A" << endl;
}
};
//BOOST_SERIALIZATION_ASSUME_ABSTRACT(Aclass)
//BOOST_CLASS_TRACKING(AClass, boost::serialization::track_never)
class BClass : public AClass{
public:
BClass(){}
virtual ~BClass(){}
private:
double c;
double d;
virtual void virtualMethod(){};
private:
friend class boost::serialization::access;
template<class Archive>
void serialize(Archive & ar, const unsigned int version)
{
ar & boost::serialization::base_object<AClass>(*this);
ar & c;
ar & d;
cout << "B" << endl;
}
};
// define export to be able to serialize through base class pointer
BOOST_CLASS_EXPORT(BClass)
BOOST_CLASS_TRACKING(BClass, boost::serialization::track_never)
class CClass : public AClass{
public:
CClass(){}
virtual ~CClass(){}
private:
double c;
double d;
virtual void virtualMethod(){};
private:
friend class boost::serialization::access;
template<class Archive>
void serialize(Archive & ar, const unsigned int version)
{
ar & boost::serialization::base_object<AClass>(*this);
ar & c;
ar & d;
cout << "C" << endl;
}
};
// define export to be able to serialize through base class pointer
BOOST_CLASS_EXPORT(CClass)
BOOST_CLASS_TRACKING(CClass, boost::serialization::track_never)
int main() {
cout << "Serializing...." << endl;
{
ofstream ofs("serialization.dat");
boost::archive::binary_oarchive oa(ofs);
for(int i=0;i<5;i++)
{
AClass* baseClassPointer = new BClass();
// serialize object through base pointer
oa << baseClassPointer;
// free the pointer so next allocation can reuse memory address
delete baseClassPointer;
}
for(int i=0;i<5;i++)
{
AClass* baseClassPointer = new CClass();
// serialize object through base pointer
oa << baseClassPointer;
// free the pointer so next allocation can reuse memory address
delete baseClassPointer;
}
}
getchar();
cout << "Deserializing..." << endl;
{
ifstream ifs("serialization.dat");
boost::archive::binary_iarchive ia(ifs);
try{
while(true){
AClass* a;
ia >> a;
delete a;
}
}catch(boost::archive::archive_exception const& e)
{
}
}
return 0;
}
执行这段代码时,结果如下:
Serializing....
A
B
B
B
B
B
C
C
C
C
C
Deserializing...
A
B
B
B
B
B
C
C
C
C
C
所以基类只被序列化一次,尽管派生类有明确的 track_never 标志。有两种不同的解决方法可以解决此问题。第一个是使用纯虚方法使基类抽象并调用宏BOOST_SERIALIZATION_ASSUME_ABSTRACT(Aclass)
,第二个是将 track_never 标志也放在基类中(在代码中注释)。
这些解决方案都不符合我的要求,因为我想在未来对系统状态进行准时序列化,这需要跟踪给定 DClass 扩展 A(不是 B 或 C)的特性,而且 AClass 不应该是抽象的。
有什么提示吗?有什么方法可以显式调用基类序列化方法,避免基类中的跟踪功能(在派生类中已经禁用)?