부스트 :: 직렬화를 사용하여 일부 데이터를 직렬화 할 때 발생하는 문제를 해결하기 위해 지난 몇 주간 힘들어했습니다.boost :: serialization - 일반 속성/기능 컨테이너에서 파생 된 클래스 직렬화
나는 작업중인 프로젝트에 클라이언트/서버 아키텍처를 사용하는 탭 편집기를 구현하려고합니다. 현재의 설계는 다음과 같이 작동
DerivedTab는베이스 탭 클래스에서 확장합니다. (이 예제 질문에서는 DerivedTab 클래스의 예제를 포함하지 않기로 선택했습니다.).
탭 클래스는 AttributeContainer에게 문자열의지도 * AttributeBase에 속성 이름을 포함 클래스를 확장합니다.
속성는 AttributeBase 연장되는 템플릿 클래스이다. 이것은 임의의 구체적인 데이터 유형을 값으로 유지할 수있는 일반 데이터 유형으로 사용하기위한 것입니다.
그리고 마침내, 는가 네트워크 연결을 통해 직렬화 할 수있는 개체가 따라야하는 계약을 식별하기 위해 기본 오브젝트 유형으로 사용되는 순수 추상 기본 클래스입니다 NetworkSerializable에서 파생 AttributeBase.
이 모든 것이 내 응용 프로그램에 정적으로 링크 된 라이브러리로 컴파일됩니다. 보시다시피, 간접적으로 진행되는 간접적 인 문제가 있으며 boost :: serialization을 사용하여 직렬화 할 때 해결해야 할 몇 가지 함정이 있습니다. 이 클래스를 직렬화하는 것과 관련이없는 모든 추가 코드를 제거했습니다. 그러나 예제 코드는 여전히 상당히 길다.
MAIN.CPP :
#include <sstream>
#include <boost/archive/text_iarchive.hpp>
#include <boost/archive/text_oarchive.hpp>
#include "Tab.h"
using namespace test;
int main(int argc, char **argv)
{
std::ostringstream oarchiveStream;
boost::archive::text_oarchive outputArchive(oarchiveStream);
Tab* tab = new Tab("temp");
bool tempBool = true;
tab->RegisterAttribute("tempBool", "a temp boolean", &tempBool);
std::string tempString("1234");
tab->RegisterAttribute("tempString", "a temp string", &tempString);
outputArchive << tab;
}
Tab.h :
#ifndef __TAB_H__
#define __TAB_H__
#include "AttributeContainer.h"
#include <boost/serialization/base_object.hpp>
namespace test
{
class Tab : public AttributeContainer
{
friend class boost::serialization::access;
public:
Tab(const std::string tabName);
virtual ~Tab();
protected:
Tab();
template<class archive>
inline void serialize_attributes(archive& ar, const unsigned int version)
{
ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(AttributeContainer);
ar & boost::serialization::make_nvp("TabName", _tabName);
}
virtual void serialize(boost::archive::text_oarchive& oa, const unsigned int version);
virtual void serialize(boost::archive::text_iarchive& ia, const unsigned int version);
private:
std::string _tabName;
};
} // namespace test
BOOST_CLASS_EXPORT_KEY(test::Tab);
#endif // #ifndef __TAB_H__
Tab.cpp :
#include "Tab.h"
BOOST_CLASS_EXPORT_IMPLEMENT(test::Tab);
using namespace test;
Tab::Tab(const std::string tabName) : _tabName(tabName)
{
}
Tab::~Tab()
{
}
Tab::Tab() : _tabName("")
{
}
void Tab::serialize(boost::archive::text_oarchive& oa, const unsigned int version)
{
std::cout << "Tab::serialize" << std::endl;
serialize_attributes(oa, version);
}
void Tab::serialize(boost::archive::text_iarchive& ia, const unsigned int version)
{
serialize_attributes(ia, version);
}
AttributeContainer.h :
#ifndef __ATTRIBUTE_CONTAINER_H__
#define __ATTRIBUTE_CONTAINER_H__
#include "NetworkSerializable.h"
#include <boost/serialization/map.hpp>
#include "Attribute.h"
namespace test
{
class AttributeContainer : public NetworkSerializable
{
friend class boost::serialization::access;
public:
std::map<std::string, AttributeBase*> _attributes;
AttributeContainer() {};
virtual ~AttributeContainer() {};
template <typename _T>
void RegisterAttribute(const std::string& name, const std::string& description, _T* var)
{
std::map<std::string, AttributeBase*>::const_iterator pos;
if ((pos = _attributes.find(name)) == _attributes.end())
{
Attribute<_T>* attribute = new Attribute<_T>(name, description, var);
_attributes.insert(std::map<std::string, AttributeBase*>::value_type(name, attribute));
}
};
template <class archive>
inline void serialize_attributes(archive& ar, const unsigned int version)
{
ar & _attributes;
};
virtual void serialize(boost::archive::text_oarchive& oa, const unsigned int version);
virtual void serialize(boost::archive::text_iarchive& ia, const unsigned int version);
}; // end class AtributeContainer
} // end namespace test
BOOST_CLASS_EXPORT_KEY(test::AttributeContainer);
#endif // #ifndef __ATTRIBUTE_CONTAINER_H__
AttributeContainer.cpp :
#include "AttributeContainer.h"
BOOST_CLASS_EXPORT_IMPLEMENT(test::AttributeContainer);
using namespace test;
void AttributeContainer::serialize(boost::archive::text_oarchive& oa, const unsigned int version)
{
std::cout << "AttributeContainer::serialize" << std::endl;
serialize_attributes(oa, version);
}
void AttributeContainer::serialize(boost::archive::text_iarchive& ia, const unsigned int version)
{
serialize_attributes(ia, version);
}
Attribute.h :
#ifndef __ATTRIBUTE_H__
#define __ATTRIBUTE_H__
#include "AttributeBase.h"
namespace test
{
template <typename _T>
class Attribute : public AttributeBase
{
friend class AttributeContainer;
friend class boost::serialization::access;
public:
typedef _T AttributeType;
Attribute() : _data(0) {}
Attribute(const std::string& name, const std::string& description, AttributeType* var) : _data(var)
{
_name = name;
_description = description;
}
virtual ~Attribute() {}
protected:
AttributeType* _data;
template <class archive>
inline void serialize_base(archive& ar, const unsigned int version)
{
ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(AttributeBase);
ar & boost::serialization::make_nvp("Value", *_data);
}
virtual void serialize(boost::archive::text_oarchive& oa, const unsigned int version)
{
std::cout << "Attribute::serialize" << std::endl;
serialize_base(oa, version);
}
virtual void serialize(boost::archive::text_iarchive& ia, const unsigned int version)
{
serialize_base(ia, version);
}
};
} // namespace test
BOOST_CLASS_EXPORT_KEY(test::Attribute<bool>);
BOOST_CLASS_EXPORT_KEY(test::Attribute<std::string>);
#endif // #ifndef __ATRIBUTE_H__
Attribute.cpp :
#include "Attribute.h"
BOOST_CLASS_EXPORT_IMPLEMENT(test::Attribute<bool>);
BOOST_CLASS_EXPORT_IMPLEMENT(test::Attribute<std::string>);
using namespace test;
AttributeBase.h :
#ifndef __ATTRIBUTE_BASE_H__
#define __ATTRIBUTE_BASE_H__
#include "NetworkSerializable.h"
#include <string>
namespace test
{
class AttributeBase : public NetworkSerializable
{
friend class AttributeContainer;
friend class boost::serialization::access;
public:
AttributeBase();
virtual ~AttributeBase();
protected:
AttributeBase& operator=(const AttributeBase&);
AttributeBase(const AttributeBase&);
protected:
std::string _name;
std::string _description;
template<class archive>
inline void serialize_attributes(archive& ar, const unsigned int version)
{
ar & boost::serialization::make_nvp("Name", _name);
ar & boost::serialization::make_nvp("Description", _description);
}
virtual void serialize(boost::archive::text_oarchive& oa, const unsigned int version);
virtual void serialize(boost::archive::text_iarchive& ia, const unsigned int version);
}; // end class AttributeBase
} // end namespace test
BOOST_SERIALIZATION_ASSUME_ABSTRACT(test::AttributeBase);
BOOST_CLASS_EXPORT_KEY(test::AttributeBase);
#endif // #ifndef __ATTRIBUTE_BASE_H__
NetworkSerializable.h :
#ifndef __NETWORK_SERIALIZABLE_H__
#define __NETWORK_SERIALIZABLE_H__
#pragma warning(disable:4244)
#include <boost/shared_ptr.hpp>
#include <boost/serialization/nvp.hpp>
#include <boost/serialization/export.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
namespace test
{
class NetworkSerializable
{
friend class boost::serialization::access;
public:
typedef std::shared_ptr<NetworkSerializable> NetworkSerializablePtr;
NetworkSerializable() {};
protected:
virtual void serialize(boost::archive::text_oarchive& oa, const unsigned int version) = 0;
virtual void serialize(boost::archive::text_iarchive& ia, const unsigned int version) = 0;
};
BOOST_SERIALIZATION_ASSUME_ABSTRACT(NetworkSerializable);
} // namespace test
#endif // #ifndef __NETWORK_SERIALIZABLE_H__
나는이 문제를 완전히 설명하기 위해 가능한 간결하고 간결하게 코드를 작성하려고 노력했습니다.
제공된 코드의 출력은 다음과 같습니다
Tab::serialize
Tab::serialize
출력해야하는 경우 : 코드의 꽤 여기에 사람이 너무 소화하기 위해 나는 매우 감사 할 것
Tab::serialize
AttributeContainer::serialize
Attribute::serialize
AttributeBase::serialize
Attribute::serialize
AttributeBase::serialize
있다
누구든지 내가 부스트 직렬화 경로를 따라 벗어났다는 통찰력을 제공 할 수 있다면.
가능한 중복 [? Boost.serialize으로 파생 된 템플릿 클래스를 직렬화하는 방법 (http://stackoverflow.com/questions/1332602 : 여기
은 당신의 코드를 기반으로 작업을 단일 파일 예제/how-to-serialize-derived-template-classes-with-boost-serialize) –
다음 번에 예제를 그대로 사용하십시오. SSCCE를 줄이면 위험을 안고있을뿐만 아니라 코드 장벽을 극복하기 위해 임의의 낯선 사람이 필요하지 않습니다. – sehe