기본 클래스 포인터를 통해 파생 클래스를 직렬화 할 때 부스트 직렬화에 몇 가지 문제가 있습니다. 시스템에서받은 객체를 직렬화하는 시스템이 필요하므로 시간이 지남에 따라 직렬화해야합니다. boost::archive::binary_oarchive
을 열고 필요할 때 객체를 직렬화 할 수 있기 때문에 이것은 실제로 문제가되지 않습니다. 빠른 속도로 메모리 주소로 객체 추적을 수행하는 것이 보였으므로 첫 번째 문제는 동일한 객체를 동일한 메모리 주소로 공유하는 여러 객체가 동일한 객체로 저장된다는 점이었습니다. 이것은 필요한 파생 클래스에서 다음 매크로를 사용하여 고정 할 수 있습니다 : 기본 클래스가 추상적이 아닌 경우부스트 (C++)에서 클래스 추적없는 파생 클래스 직렬화
BOOST_CLASS_TRACKING(className, boost::serialization::track_never)
이는, 그러나 다시, 기본 클래스가 제대로 잘 직렬화되지 않은 작품. 다음 예제에서는 기본 클래스 serialization 메서드가 첫 번째 개체와 함께 한 번만 호출됩니다. 다음에서는 객체가 다른 유형이지만 이전에이 객체가 직렬화되었다고 가정합니다. 이 코드 부분을 실행하면
#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;
}
이 결과는 다음과 같다 : 파생 된 클래스가 명시 적으로 track_never 플래그이 있지만
Serializing....
A
B
B
B
B
B
C
C
C
C
C
Deserializing...
A
B
B
B
B
B
C
C
C
C
C
가 기본 클래스는 한 번만 직렬화된다. 이 문제를 해결하기위한 두 가지 다른 해결 방법이 있습니다. 첫 번째는 순수 가상 메서드를 사용하여 기본 클래스를 추상화하고 매크로
BOOST_SERIALIZATION_ASSUME_ABSTRACT(Aclass)
을 호출하는 것이며 두 번째는 기본 클래스 (코드에 주석 처리 됨)에 track_never 플래그를 넣는 것입니다. 시스템 상태의 향후 정시 직렬화에서 원하는 DLC (A 또는 B 또는 C가 아닌) 확장 기능을 필요로하므로이 솔루션 중 어느 것도 내 요구 사항을 충족시키지 못합니다. 또한 AClass는 추상적이 아니어야한다.
힌트가 있습니까? 명시 적으로 기본 클래스의 직렬화 메서드를 호출하여 기본 클래스의 추적 기능을 피하는 방법이 있습니까? (파생 클래스에서 이미 비활성화되어 있습니다.)
boost가 A가 가상이 아니더라도 (즉,'BOOST_SERIALIZATION_ASSUME_ABSTRACT (Aclass)'줄의 주석 처리를 제거하고 컴파일하려고 시도한다고 가정)을 가정 할 수 있습니까? – Synxis