Я смотрел на библиотеку сериализации boost, и навязчивый способ обеспечить поддержку сериализации - определить функцию-член с подписью (упрощение):
class ToBeSerialized {
public:
//Define this to support serialization
//Notice not virtual function!
template<class Archive>
void serialize(Archive & ar)
{.....}
};
Более того, один из способов поддержки сериализации производных классов через базовые указатели — использовать макрос типа:
//No mention to the base class(es) from which Derived_class inherits
BOOST_CLASS_EXPORT_GUID(Derived_class, "derived_class")
где Derived_class — это некоторый класс, который наследуется от базового класса, скажем, Base_class. Благодаря этому макросу можно корректно сериализовать классы типа Derived_class через указатели на Base_class.
Вопрос в следующем: я использую C++ для написания абстрактных фабрик, реализованных через карту из std::string в (указатель на) функции, которые возвращают объекты нужного типа (и все в порядке благодаря ковариантным типам).
Hover Я не вижу, как я мог бы использовать приведенную выше функцию-член шаблона невиртуальной сериализации для правильной десериализации (т.е. создания) объекта, не зная его типа (но предполагая, что информация о типе была сохранена сериализатором, скажем, в нить).
То, что я хотел бы сделать (сохраняя ту же номенклатуру, что и выше), выглядит примерно так:
XmlArchive xmlArchive; //A type or archive
xmlArchive.open("C:/ser.txt"); //Contains type information for the serialized class
Base_class* basePtr = Factory<Base_class>::create("derived_class",xmlArchive);
с функцией справа, создающей объект в куче типа Derived_class (с помощью конструктора по умолчанию, это та часть, которую я знаю, как решить) и вызывая функцию сериализации xmlArchive (здесь я застрял!), т.е. что-то типа:
Base_class* Factory<Base_class>::create("derived_class",xmlArchive)
{
Base_class* basePtr = new Base_class; //OK, doable, usual map string to pointer to function
static_cast<Derived_class*>( basePtr )->serialize( xmlArchive ); //De-serialization, how?????
return basePtr;
}
Я уверен, что это можно сделать (ускоренная сериализация делает это, но его код непроницаем! :P), но я не могу понять, как это сделать. Основная проблема заключается в том, что функция сериализации является шаблонной функцией. Поэтому у меня не может быть указателя на общую шаблонную функцию. Поскольку смысл написания шаблонной функции сериализации состоит в том, чтобы сделать код универсальным (т.е. не нужно переписывать функцию сериализации для разных Архиваторов), нет смысла регистрировать все производные классы для всех возможных типов архивов. , как:
MY_CLASS_REGISTER(Derived_class, XmlArchive);
MY_CLASS_REGISTER(Derived_class, TxtArchive);
...
На самом деле в моем коде я полагаюсь на перегрузку, чтобы получить правильное поведение:
void serialize( XmlArchive& archive, Derived_class& derived );
void serialize( TxtArchive& archive, Derived_class& derived );
...
Ключевым моментом, о котором следует помнить, является то, что тип архива всегда известен, т.е. я никогда не использую полиморфизм времени выполнения для класса архива... (опять же я использую перегрузку для типа архива).
Любое предложение, чтобы помочь мне?
Заранее большое спасибо!
Ваше здоровье