如何从序列化数据中“反序列化”派生类?或者我应该说,是否有更好的方法将数据“反序列化”到派生类中?
例如,假设您有一个纯虚拟基类 (B),它被其他三个类 X、Y 和 Z 继承。此外,我们有一个方法 serialize(),它将转换 X:B、Y :B 和 Z:B 转化为序列化数据。
这样它就可以通过套接字、命名管道等传输到远程进程。
我遇到的问题是,我们如何从序列化数据创建合适的对象?
我能想出的唯一解决方案是在序列化数据中包含一个标识符,指示最终派生对象类型。接收方首先从序列化数据解析派生类型字段,然后使用 switch 语句(或类似的某种逻辑)调用适当的构造函数。
例如:
B deserialize( serial_data )
{
parse the derived type from the serial_data
switch (derived type)
case X
return X(serial_data)
case Y
return Y(serial_data)
case Z
return Z(serial_data)
}
因此,在了解派生对象类型后,我们调用适当的派生类型构造函数。
但是,这感觉很尴尬和麻烦。我希望有一种更 Eloquent 方式来做到这一点。有吗?
最佳答案
事实上,这是一个比称为 Virtual Constructor
的序列化更普遍的问题.
传统方法是 Factory
,它基于 ID 返回正确的派生类型。有两种解决方案:
switch
您注意到的方法,尽管您需要在堆上分配prototype
方法
原型(prototype)方法是这样的:
// Cloneability
class Base
{
public:
virtual Base* clone() const = 0;
};
class Derived: public Base
{
public:
virtual Derived* clone() const { return new Derived(*this); }
};
// Factory
class Factory
{
public:
Base* get(std::string const& id) const;
void set(std::string const& id, Base* exemplar);
private:
typedef std::map < std::string, Base* > exemplars_type;
exemplars_type mExemplars;
};
制作 Factory
有点传统一个单例,但这完全是另一回事。
对于正确的反序列化,如果你有一个虚方法会更容易 deserialize
调用对象。
编辑:工厂如何运作?
在 C++ 中,您无法创建您不知道的类型。因此,上面的想法是构建一个 Derived
的任务。对象被赋予 Derived
类,通过 clone
方法。
接下来是 Factory
.我们将使用 map
这会将“标签”(例如 "Derived"
)关联到对象的实例(在这里说 Derived
)。
Factory factory;
Derived derived;
factory.set("Derived", &derived);
现在,当我们想要创建一个我们在编译时不知道其类型的对象时(因为类型是动态决定的),我们将一个标签传递给工厂并要求返回一个对象。
std::unique_ptr<Base> base = factory.get("Derived");
在幕后,Factory
会找到 Base*
关联到 "Derived"
标记并调用 clone
对象的方法。这实际上(在这里)创建一个运行时类型的对象 Derived
.
我们可以使用 typeid
来验证这一点运算符(operator):
assert( typeid(base) == typeid(Derived) );
关于c++ - 你如何从序列化数据中获取 'de-serialize' 的派生类?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3268801/