В моем приложении есть агенты разных типов. Я планирую использовать форсированную сериализацию для отправки/получения данных между агентами (путем отправки/получения, я на самом деле подразумеваю операцию записи/чтения файла цепочки сериализации)правильный тип-литой для ускорения де-сериализации разных производных классов
Получающий агент может получать данные из разных данных, тип которых не является заранее известных. Предположим, что формат данных имеет общую структуру, как это:
class Base
{
public:
int message_type_id;
}
class Derived_1
{
public:
Derived_1(int message_type_id_):message_type_id(message_type_id_){}
struct data_1 {...};
};
class Derived_2
{
public:
Derived_2(int message_type_id_):message_type_id(message_type_id_){}
struct data_2 {...};
};
отправляющий агент может отправить (т.е. сериализации) любого из двух типов производных. Аналогично, принимающий агент может получать (то есть де-сериализует) любой из двух производных типов; а то, что я могу видеть в tutorial(Dumping derived classes through base class pointers), как это:
void save()
{
std::ofstream file("archive.xml"); //target file
boost::archive::xml_oarchive oa(file);
oa.register_type<date>();// you know what you are sending, so you make proper modifications here to do proper registration
base* b = new date(15, 8, 1947);
oa & BOOST_SERIALIZATION_NVP(b);
}
void load()
{
std::ifstream file("archive.xml"); //target file
boost::archive::xml_iarchive ia(file);
ia.register_type<date>();// I don't know which derived class I am receiving, so I can't do a proper registration
base *dr;
ia >> BOOST_SERIALIZATION_NVP(dr);
date* dr2 = dynamic_cast<date*> (dr);
std::cout << dr2;
}
, как вы можете видеть, xml_oarchive
и xml_iarchive
сделать register_type<date>
до сериализации/десериализации. поэтому получающая сторона будет знать заранее, что до dynamic_cast
. , тогда как в моем случае, так как я знаю, что я отправляю, я могу сделать правильную регистрацию & сериализации на основе case-to-case. Тем не менее, на принимающей стороне, я не знаю заранее, что регистрировать, а что - динамически.
Есть ли способ, которым я могу заранее указать тип, чтобы получающий мог сделать кастинг?
благодаря
EDIT: Вот упрощенная модификация demo.cpp я сохранить объект, а затем восстановить его.
#include <cstddef> // NULL
#include <iomanip>
#include <iostream>
#include <fstream>
#include <string>
#include <boost/archive/tmpdir.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/serialization/base_object.hpp>
#include <boost/serialization/utility.hpp>
#include <boost/serialization/list.hpp>
#include <boost/serialization/assume_abstract.hpp>
/*
bus_stop is the base class.
bus_stop_corner and bus_stop_destination are derived classes from the above base class.
bus_route has a container that stores pointer to the above derived classes
*/
class bus_stop
{
friend class boost::serialization::access;
virtual std::string description() const = 0;
template<class Archive>
void serialize(Archive &ar, const unsigned int version)
{
ar & type;
}
protected:
public:
std::string type;
bus_stop(){type = "Base";}
virtual ~bus_stop(){}
};
BOOST_SERIALIZATION_ASSUME_ABSTRACT(bus_stop)
class bus_stop_corner : public bus_stop
{
friend class boost::serialization::access;
virtual std::string description() const
{
return street1 + " and " + street2;
}
template<class Archive>
void serialize(Archive &ar, const unsigned int version)
{
// save/load base class information
ar & boost::serialization::base_object<bus_stop>(*this);
ar & street1 & street2;
}
public:
std::string street1;
std::string street2;
bus_stop_corner(){}
bus_stop_corner(
const std::string & _s1, const std::string & _s2
) :
street1(_s1), street2(_s2)
{
type = "derived_bs_corner";
}
};
class bus_stop_destination : public bus_stop
{
friend class boost::serialization::access;
virtual std::string description() const
{
return name;
}
template<class Archive>
void serialize(Archive &ar, const unsigned int version)
{
ar & boost::serialization::base_object<bus_stop>(*this) & name;
}
public:
std::string name;
bus_stop_destination(){}
bus_stop_destination(
const std::string & _name
) :
name(_name)
{
type = "derived_bs_destination";
}
};
class bus_route
{
friend class boost::serialization::access;
typedef bus_stop * bus_stop_pointer;
template<class Archive>
void serialize(Archive &ar, const unsigned int version)
{
ar.register_type(static_cast<bus_stop_corner *>(NULL));
ar.register_type(static_cast<bus_stop_destination *>(NULL));
ar & stops;
}
public:
std::list<bus_stop_pointer> stops;
bus_route(){}
void append(bus_stop *_bs)
{
stops.insert(stops.end(), _bs);
}
};
//BOOST_CLASS_VERSION(bus_route, 2)
void save_schedule(const bus_route s, const char * filename){
// make an archive
std::ofstream ofs(filename);
boost::archive::text_oarchive oa(ofs);
oa << s;
}
void
restore_schedule(bus_route &s, const char * filename)
{
// open the archive
std::ifstream ifs(filename);
boost::archive::text_iarchive ia(ifs);
// restore the schedule from the archive
ia >> s;
}
int main(int argc, char *argv[])
{
bus_stop *bs1 = new bus_stop_corner(
"First St", "Second st"
);
bus_stop *bs2 = new bus_stop_destination(
"myName"
);
// make a routes
bus_route original_route;
original_route.append(bs1);
original_route.append(bs2);
std::string filename1(boost::archive::tmpdir());
filename1 += "/demofile1.txt";
save_schedule(original_route, filename1.c_str());
bus_route new_route ;
restore_schedule(new_route, filename1.c_str());
////////////////////////////////////////////////////////
std::string filename2(boost::archive::tmpdir());
filename2 += "/demofile2.txt";
save_schedule(new_route, filename2.c_str());
delete bs1;
delete bs2;
return 0;
}
старых и новых объекты не равен сог снова сохранение (сериализация) новый объект в другие результаты файлов в другом (пустом) содержании. Не могли бы вы сообщить мне, как я могу исправить этот код, чтобы успешно десериализовать производные классы? большое спасибо
EDIT-2 В приведенном выше кодексе нет ничего плохого (после того, как была исправлена небольшая опечатка). Я отвечаю на свой вопрос здесь, потому что есть другой хороший подход, предложенный кем-то другим. Итак, Ответьте на мой первый вопрос: Пока вы регистрируете производные типы в главной функции сериализации (в приведенном выше случае: serialize() в классе bus_route) все должно быть хорошо.
спасибо за помощь
@ meabyte1024 благодарит за прекрасный ответ. Но, будучи новичком в сериализации, я не понимаю, как использование справки XML и общей версии <> позволяет решить проблему. Я думаю, что более одного типа производного класса не изменят правильный результат. Как он работает, даже не регистрируя производные классы? – rahman
@rahman, давайте выясним, в чем проблема. Как только я понял, вам нужно десериализовать производные классы, не имеет значения, либо это «Derived_1» или «Derived_2». Правильно ли это?Если да, то мой пример демонстрирует это. Часть десериализации функции 'test' работает с экземпляром класса' boost :: shared_ptr '(' pDst'), и сериализация создает правильный экземпляр производного класса. Программа выводит «Успех». О втором вопросе есть скрытая регистрация в макросе 'BOOST_CLASS_EXPORT_GUID'. –
megabyte1024
ответ на ваш вопрос - да. Ваш комментарий также разъясняет некоторые из моих проблем. Тем не менее, чтобы прояснить концепцию, не могли бы вы сообщить мне, что не так с моим примером? (последний фрагмент кода). – rahman