C++ 序列化-序列化从泛型属性/功能容器派生的类
在过去的几周里,我一直在努力解决使用boost::serialization序列化某些数据时遇到的问题 我正在尝试实现一个选项卡式编辑器,它利用客户机/服务器体系结构来处理我正在处理的项目。当前设计的工作原理如下:C++ 序列化-序列化从泛型属性/功能容器派生的类,c++,templates,serialization,boost,containers,C++,Templates,Serialization,Boost,Containers,在过去的几周里,我一直在努力解决使用boost::serialization序列化某些数据时遇到的问题 我正在尝试实现一个选项卡式编辑器,它利用客户机/服务器体系结构来处理我正在处理的项目。当前设计的工作原理如下: DerivedTab从基本选项卡扩展而来。(对于这个示例问题,我选择不包括DerivedTab类的示例。) 选项卡类扩展了AttributeContainer类,该类包含字符串属性名称到AttributeBase*的映射 属性是扩展属性库的模板类。它打算用作一种通用数据类型,可以保
- DerivedTab从基本选项卡扩展而来。(对于这个示例问题,我选择不包括DerivedTab类的示例。)
- 选项卡类扩展了AttributeContainer类,该类包含字符串属性名称到AttributeBase*的映射
- 属性是扩展属性库的模板类。它打算用作一种通用数据类型,可以保存任何具体数据类型的值
- 最后,AttributeBase源自NetworkSerializable,它是一个纯抽象基类,用作基本对象类型,用于标识可通过网络连接序列化的对象必须遵循的约定
#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::serialize
AttributeContainer::serialize
Attribute::serialize
AttributeBase::serialize
Attribute::serialize
AttributeBase::serialize
这里有很多代码需要消化,因此如果有人能够提供我可能在boost序列化路径上迷失的任何见解,我将非常感激。简而言之:您的
序列化成员函数应该而不是虚拟的。通过调用boost::serialization::base_object
在Tab::serialize_attributes
内部创建的static_cast(this)->serialize(…)
,通过虚拟函数分派返回Tab::serialize
,使它们成为虚拟结果
下面是一个基于您的代码的工作单文件示例:
namespace serial_test
{
using namespace std;
class NetworkSerializable {
friend class boost::serialization::access;
public:
typedef std::shared_ptr<NetworkSerializable> NetworkSerializablePtr;
NetworkSerializable() {};
protected:
// void serialize(boost::archive::text_oarchive& oa, const unsigned int version) = 0;
// void serialize(boost::archive::text_iarchive& ia, const unsigned int version) = 0;
};
BOOST_SERIALIZATION_ASSUME_ABSTRACT(NetworkSerializable);
class AttributeBase : public NetworkSerializable {
friend class AttributeContainer;
friend class boost::serialization::access;
public:
AttributeBase() {}
virtual ~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);
}
void serialize(boost::archive::text_oarchive& oa, const unsigned int version) {
cout << "AttributeBase::serialize" << endl;
serialize_attributes(oa, version);
}
void serialize(boost::archive::text_iarchive& ia, const unsigned int version) {
serialize_attributes(ia, version);
}
}; // end class AttributeBase
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>
void serialize_base(archive& ar, const unsigned int version) {
ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(AttributeBase);
ar & boost::serialization::make_nvp("Value", *_data);
}
void serialize(boost::archive::text_oarchive& oa, const unsigned int version) {
std::cout << "Attribute::serialize" << std::endl;
serialize_base(oa, version);
}
void serialize(boost::archive::text_iarchive& ia, const unsigned int version) {
serialize_base(ia, version);
}
};
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>
void serialize_attributes(archive& ar, const unsigned int version) {
ar & _attributes;
};
void serialize(boost::archive::text_oarchive& oa, const unsigned int version) {
std::cout << "AttributeContainer::serialize" << std::endl;
serialize_attributes(oa, version);
}
void serialize(boost::archive::text_iarchive& ia, const unsigned int version) {
serialize_attributes(ia, version);
}
}; // end class AtributeContainer
class Tab : public AttributeContainer {
friend class boost::serialization::access;
public:
Tab(const std::string tabName)
: _tabName(tabName) {}
virtual ~Tab() {}
protected:
Tab()
: _tabName("") {}
template<class archive>
inline void serialize_attributes(archive& ar, const unsigned int version) {
// ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(AttributeContainer);
ar & boost::serialization::base_object<AttributeContainer>(*this);
ar & boost::serialization::make_nvp("TabName", _tabName);
}
void serialize(boost::archive::text_oarchive& oa, const unsigned int version) {
std::cout << "Tab::serialize" << std::endl;
serialize_attributes(oa, version);
}
void serialize(boost::archive::text_iarchive& ia, const unsigned int version) {
serialize_attributes(ia, version);
}
private:
std::string _tabName;
};
void test() {
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;
}
} // namespace serial_test
BOOST_SERIALIZATION_ASSUME_ABSTRACT(serial_test::AttributeBase);
BOOST_CLASS_EXPORT_KEY(serial_test::AttributeBase);
BOOST_CLASS_EXPORT_KEY(serial_test::Attribute<bool>);
BOOST_CLASS_EXPORT_KEY(serial_test::Attribute<string>);
BOOST_CLASS_EXPORT_IMPLEMENT(serial_test::Attribute<bool>);
BOOST_CLASS_EXPORT_IMPLEMENT(serial_test::Attribute<string>);
BOOST_CLASS_EXPORT_KEY(serial_test::Tab);
BOOST_CLASS_EXPORT_IMPLEMENT(serial_test::Tab);
名称空间串行\u测试
{
使用名称空间std;
类NetworkSerializable{
好友类boost::serialization::access;
公众:
typedef std::shared_ptr NetworkSerializablePtr;
NetworkSerializable(){};
受保护的:
//void serialize(boost::archive::text_oarchive&oa,const unsigned int version)=0;
//void serialize(boost::archive::text_iarchive&ia,const unsigned int version)=0;
};
BOOST_序列化_假设_抽象(NetworkSerializable);
类AttributeBase:公用网络可序列化{
好友类属性容器;
好友类boost::serialization::access;
公众:
AttributeBase(){}
虚拟~AttributeBase(){}
受保护的:
std::string _name;
std::字符串_描述;
模板
内联void序列化_属性(存档&ar,常量unsigned int版本){
ar&boost::serialization::make_nvp(“名称”,_名称);
ar&boost::序列化::生成nvp(“描述”,描述);
}
void序列化(boost::archive::text\u oarchive&oa,const unsigned int版本){
不可能重复的请,下次,把你的例子切中要害。在简化为SSCCE时,你不仅要冒发现问题的风险你自己,但你也不需要随机陌生人来处理代码墙。这正是问题所在。我想我太专注于确保我有合适的宏来描述合适的场景,甚至没有想到我拥有纯抽象基类的策略可以确保NetworkSerializable的派生类定义::序列化()这就是问题所在。非常感谢您指出这一点!!!这个故事的寓意是,当使用boost::serialization时,::serialization方法不应被虚拟化。我引用了上面标记为重复的帖子,并尝试将其实现作为指南。显然我忽略了一些内容。再次感谢!我很高兴您的问题得到解决。请继续赛德接受答案;)
#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__
#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);
}
#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__
#include "Attribute.h"
BOOST_CLASS_EXPORT_IMPLEMENT(test::Attribute<bool>);
BOOST_CLASS_EXPORT_IMPLEMENT(test::Attribute<std::string>);
using namespace test;
#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__
#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
namespace serial_test
{
using namespace std;
class NetworkSerializable {
friend class boost::serialization::access;
public:
typedef std::shared_ptr<NetworkSerializable> NetworkSerializablePtr;
NetworkSerializable() {};
protected:
// void serialize(boost::archive::text_oarchive& oa, const unsigned int version) = 0;
// void serialize(boost::archive::text_iarchive& ia, const unsigned int version) = 0;
};
BOOST_SERIALIZATION_ASSUME_ABSTRACT(NetworkSerializable);
class AttributeBase : public NetworkSerializable {
friend class AttributeContainer;
friend class boost::serialization::access;
public:
AttributeBase() {}
virtual ~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);
}
void serialize(boost::archive::text_oarchive& oa, const unsigned int version) {
cout << "AttributeBase::serialize" << endl;
serialize_attributes(oa, version);
}
void serialize(boost::archive::text_iarchive& ia, const unsigned int version) {
serialize_attributes(ia, version);
}
}; // end class AttributeBase
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>
void serialize_base(archive& ar, const unsigned int version) {
ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(AttributeBase);
ar & boost::serialization::make_nvp("Value", *_data);
}
void serialize(boost::archive::text_oarchive& oa, const unsigned int version) {
std::cout << "Attribute::serialize" << std::endl;
serialize_base(oa, version);
}
void serialize(boost::archive::text_iarchive& ia, const unsigned int version) {
serialize_base(ia, version);
}
};
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>
void serialize_attributes(archive& ar, const unsigned int version) {
ar & _attributes;
};
void serialize(boost::archive::text_oarchive& oa, const unsigned int version) {
std::cout << "AttributeContainer::serialize" << std::endl;
serialize_attributes(oa, version);
}
void serialize(boost::archive::text_iarchive& ia, const unsigned int version) {
serialize_attributes(ia, version);
}
}; // end class AtributeContainer
class Tab : public AttributeContainer {
friend class boost::serialization::access;
public:
Tab(const std::string tabName)
: _tabName(tabName) {}
virtual ~Tab() {}
protected:
Tab()
: _tabName("") {}
template<class archive>
inline void serialize_attributes(archive& ar, const unsigned int version) {
// ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(AttributeContainer);
ar & boost::serialization::base_object<AttributeContainer>(*this);
ar & boost::serialization::make_nvp("TabName", _tabName);
}
void serialize(boost::archive::text_oarchive& oa, const unsigned int version) {
std::cout << "Tab::serialize" << std::endl;
serialize_attributes(oa, version);
}
void serialize(boost::archive::text_iarchive& ia, const unsigned int version) {
serialize_attributes(ia, version);
}
private:
std::string _tabName;
};
void test() {
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;
}
} // namespace serial_test
BOOST_SERIALIZATION_ASSUME_ABSTRACT(serial_test::AttributeBase);
BOOST_CLASS_EXPORT_KEY(serial_test::AttributeBase);
BOOST_CLASS_EXPORT_KEY(serial_test::Attribute<bool>);
BOOST_CLASS_EXPORT_KEY(serial_test::Attribute<string>);
BOOST_CLASS_EXPORT_IMPLEMENT(serial_test::Attribute<bool>);
BOOST_CLASS_EXPORT_IMPLEMENT(serial_test::Attribute<string>);
BOOST_CLASS_EXPORT_KEY(serial_test::Tab);
BOOST_CLASS_EXPORT_IMPLEMENT(serial_test::Tab);