我在看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。由于这个宏,可以通过指向 Base_class 的指针正确地序列化 Derived_class 类型的类。
问题是: 我在 C++ 中使用通过从 std::string 到(指向)函数的映射来编写抽象工厂,这些函数返回所需类型的对象(由于协变类型,一切都很好)。
悬停我看不出如何使用上述非虚拟序列化模板成员函数在不知道其类型的情况下正确反序列化(即构造)对象(但假设类型信息已由序列化程序存储,用字符串说)。
我想做的(保持与上面相同的命名法)类似于以下内容:
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;
}
我相信这是可以做到的(boost serialize 做到了,但它的代码是难以理解的!: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 );
...
要记住的关键点是存档类型始终是已知的,即我从不对存档类使用运行时多态性......(我再次对存档类型使用重载)。
有什么建议可以帮助我吗?
非常感谢您!
干杯
最佳答案
您所需要的只是在存储派生类型的信息之前存储某种标识符。然后在阅读时使用您首先阅读的那个标识符将您引导到一个工厂,该工厂然后可以正确解释下一个信息 block 并生成您的派生类型。这可能是 boost::serialization 在非常基本的层面上所做的。也许是这样的:
ar >> type;
Base_class* basePtr = Factory<Base_class>::create(type,xmlArchive);
然后你有一个看起来像这样的对象 map :
<p></p>
<p>struct reader_base { virtual void load(xmlArchive, base_ptr) = 0; }
template < typename T >
struct reader : reader_base
{
virtual void load(xmlArchive, base_ptr)
{
static_cast<T*>(base_ptr)->serialize(xmlArchive);
}
};
</p>
关于C++ 模板化工厂构造函数/反序列化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2900729/