使用特定于环境的状态序列化多态类(Serializing polymorphic classes with environment

编程入门 行业动态 更新时间:2024-10-27 00:34:34
使用特定于环境的状态序列化多态类(Serializing polymorphic classes with environment-specific state)

我有一些看起来像这样的类:

class Base { public: virtual ~Base() {} ... }; class Derived1 { OuterState1& outerState; InnerState1 innerState; ... template <typename Ar> void serialize(Ar& ar, const unsigned int /*version*/) { ar & innerState; } public: Derived1(OuterState1& outerState) : outerState(outerState) {} ... }; class Derived2 { OuterState2& outerState; InnerState2 innerState; ... template <typename Ar> void serialize(Ar& ar, const unsigned int /*version*/) { ar & innerState; } public: Derived1(OuterState2& outerState) : outerState(outerState) {} ... };

基本上,类的状态取决于外部环境,我不想序列化它。 对于不同的子类,该状态可能不同。 我想序列化这个类。 一个好处是boost :: serialization可以很好地处理多态类,但在我看来,这对我来说还不够好。 我可以找到以下方法来序列化这些对象,我不喜欢它们:

将全局变量用于外部状态。 现在我们要么在类中使用这些全局变量,要么重载load_construct_data()并从这个全局变量创建对象。 这个解决方案的问题在于它需要全局变量,这通常是一个糟糕的设计,并且如果程序需要处理多个这样的状态,则会中断。

不要使用Boost的多态序列化功能。 而是将实际类型保存在枚举中,然后以非多态方式保存对象。 加载时,加载类型枚举,然后在开关中创建具有适当外部状态的相应类型的对象,然后以非多态方式加载对象。 这个问题是我必须做很多手动编码,这些编码会由Boost自动完成,如果我想序列化这些对象的集合,它就无法工作。

这个问题有更好,更优雅的解决方案吗?

I have some classes that look roughly like this:

class Base { public: virtual ~Base() {} ... }; class Derived1 { OuterState1& outerState; InnerState1 innerState; ... template <typename Ar> void serialize(Ar& ar, const unsigned int /*version*/) { ar & innerState; } public: Derived1(OuterState1& outerState) : outerState(outerState) {} ... }; class Derived2 { OuterState2& outerState; InnerState2 innerState; ... template <typename Ar> void serialize(Ar& ar, const unsigned int /*version*/) { ar & innerState; } public: Derived1(OuterState2& outerState) : outerState(outerState) {} ... };

Basically, the classes have a state that depends on the outside environment, and I don't want to serialize it. This state may be different for the different subclasses. I want to serialize this class. A good thing is that boost::serialization handles polymorphic classes well, but it seems to me that not well enough for me. I could find the following ways to serialize these objects, neither which I like:

Use global variables for the outer state. Now either we use these global variables inside the class, or overload load_construct_data() and create the objects from this global variable. The problem with this solution is that it requires global variables, which is generally a bad design, and breaks if the program needs to handle more than one such states.

Do not use the polymorphic serialization feature of Boost. Instead, save the actual type in an enum, then save the object non-polymorphically. When loading, load the type enum, then in a switch create the object of the appropriate type with the appropriate outer state, then load the object non-polymorphically. The problem with this is that I have to do a lot of manual coding that would automagically be done by Boost, and that it doesn't work if I want to serialize a collection of such objects.

Is there any better, more elegant solution for this problem?

最满意答案

解决方案是将特定于环境的状态保存为类中的指针。 然后在实际类之前将其保存/加载到存档中,并修改其值。 所以基类的序列化看起来像这样:

class Derived1 { OuterState1& outerState; InnerState1 innerState; ... template <typename Ar> void serialize(Ar& ar, const unsigned int /*version*/) { ar & innerState; } public: Derived1(OuterState1& outerState) : outerState(outerState) {} const OuterState1& getOuterState() const { return outerState; } ... }; template <typename Ar> void save_construct_data(Ar& ar, const Derived1* object, const unsigned int /*version*/) { ar << &object.getOuterState(); } template <typename Ar> void load_construct_data(Ar& ar, Derived1* object, const unsigned int /*version*/) { OuterState1* state; ar >> state; ::new(object)Derived1{*state}; }

使环境特定对象的序列化为NOP。

template <typename Ar> void serialize(Ar&, OuterState1&, const unsigned int) { }

保存时,请执行以下操作:

OuterState1 outerState1; OuterState2 outerState2; std::shared_ptr<Base> object = getObject(); ... // saving starts now archive << outerState1 << outerState2 << object; ...

加载时,加载状态,然后覆盖它们。 假设outerState1和outerState2位于与之前相同的位置,并且已经具有新的期望值。

std::shared_ptr<Base> object; archive >> outerState1 >> outerState2 >> object;

另一方面,问题中提供的代码并不完整。 需要完成基类序列化,但现在不是这一点。

The solution is to save the environment-specific state as a pointer in the class. Then save/load it in the archive before the actual classes, and modify its value. So serialization of the base class looks something like this:

class Derived1 { OuterState1& outerState; InnerState1 innerState; ... template <typename Ar> void serialize(Ar& ar, const unsigned int /*version*/) { ar & innerState; } public: Derived1(OuterState1& outerState) : outerState(outerState) {} const OuterState1& getOuterState() const { return outerState; } ... }; template <typename Ar> void save_construct_data(Ar& ar, const Derived1* object, const unsigned int /*version*/) { ar << &object.getOuterState(); } template <typename Ar> void load_construct_data(Ar& ar, Derived1* object, const unsigned int /*version*/) { OuterState1* state; ar >> state; ::new(object)Derived1{*state}; }

Make serialization of the environment specific object a NOP.

template <typename Ar> void serialize(Ar&, OuterState1&, const unsigned int) { }

When saving, do it like this:

OuterState1 outerState1; OuterState2 outerState2; std::shared_ptr<Base> object = getObject(); ... // saving starts now archive << outerState1 << outerState2 << object; ...

When loading, load the states, then override them. Suppose outerState1 and outerState2 are located at the same position as before, and already has the new, desired value.

std::shared_ptr<Base> object; archive >> outerState1 >> outerState2 >> object;

On another note, the code presented in the question is not complete. The base class serialization needs to be done, but that's beside the point now.

更多推荐

serialize,对象,状态,电脑培训,计算机培训,IT培训"/> <meta name="description&q

本文发布于:2023-08-06 19:57:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1455656.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:状态   环境   序列化   多态   classes

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!