【问题标题】:C/C++: Should serialization methods be class members?C/C++:序列化方法应该是类成员吗?
【发布时间】:2014-09-14 17:54:36
【问题描述】:

假设我们有一个复杂(即非原始)类ComplexObject 定义如下:

class A{...};

class B{...};

class C{...};

class ComplexObject
{
private:
    A _fieldA;
    B _fieldB;
    C _fieldC;
};

我想实现一个序列化程序,将ComplexObject 的实例序列化为二进制形式。根据我在 C# 方面的经验,我基本上看到了 3 种不同的方式来实现序列化程序。

  1. ComplexObject 和“子”类ABC 的定义中定义一个serialize(binarystream&) 方法。 ComplexObject 中定义的 serialize 方法将递归调用子成员的方法。
  2. 创建一个单独的类,其中包含用于序列化每个ComplexObjectABC 的方法。用于序列化ComplexObject 的方法将递归调用子成员的方法。当然,必须在类中定义 getter 才能为序列化程序检索私有字段。
  3. 使用反射生成对象的模板,并根据生成的模板将所有可序列化的字段写入表中。

不幸的是,我认为反射在 C++ 中将非常难以使用,因此我将远离第三种选择。我已经看到选项 1 和 2 都经常使用(在 C# 中)。

选项 1 相对于选项 2 的一个优势是它允许从 ComplexObject 派生的类,方法是将 serilalize(binarystream&) 方法标记为虚拟。但是,它会添加到对象的成员函数列表中并使程序员感到困惑。您没有看到在 std::string 中定义了 serialize 方法,是吗?

另一方面,选项 2 取出所有序列化方法并将其组合在一起以使事情更整洁。但是,我认为要适应 ComplexObject 的派生类并不容易。

在什么情况下应该使用每个选项(1 和 2)?

【问题讨论】:

    标签: c++ class serialization polymorphism


    【解决方案1】:

    我选择“两者”。序列化在对象中具有组件和(模板化)独立功能。

    例如:

    class Serialization_Interface
    {
      public:
        virtual void load_from_buffer(uint8_t*& buffer_ptr) = 0;
    };
    
    void Load_From_Buffer(unsigned int& number, uint8_t*& buffer_pointer)
    {
      number = *((unsigned int *) buffer_ptr);
      buffer_pointer += sizeof(unsigned int);
    }
    
    template <class Object>
    void Load_From_Buffer(Object& obj, uint8_t*& buffer_pointer)
    {
      obj.load_from_buffer(buffer_pointer);
    }
    

    不要将自己限制在两个选择中。总有第三种选择。 :-)

    另外,不要重新发明轮子,请查看 Boost::serialization。

    【讨论】:

      【解决方案2】:

      C++ 没有反射,但这并不意味着序列化代码需要手工编写。

      您可以使用代码生成器(例如,协议缓冲区)从简单的描述中创建序列化代码。当然,这种描述格式不支持用于创建公共 API 的丰富 C++ 功能,但您可以采用代码生成器创建的数据结构类型并将其嵌入到您的“真实”类中,直接嵌入或通过 pimpl。这样你就可以在你的类中编写所有非序列化行为,但它自己没有任何数据,它依赖于序列化对象来存储数据。

      它基本上就像你的方法 #2,但应用了控制反转。序列化器逻辑不会进入您的类来访问数据,而是负责将数据存储在您的类也可以使用的地方。

      【讨论】:

        【解决方案3】:

        我不会为自制的序列化程序而烦恼。 (请注意,设计反序列化比序列化更难......) 我宁愿使用某行:

        https://code.google.com/p/protobuf/

        http://android-developers.blogspot.com/2014/06/flatbuffers-memory-efficient.html

        或提升(您也可以查看他们是如何解决类似问题的) http://www.boost.org/doc/libs/1_56_0/libs/serialization/doc/index.html

        回到你的困境。 将所有序列化代码分组在一个类中是一个坏主意,因为这个类会随着每个新的可序列化对象而增长。您可以为每个“可序列化”类使用朋友“序列化器”类, 或者使用友元方法/运算符

        【讨论】:

        • 虽然其他答案都很好,但我发现提出的建议(重载朋友
        猜你喜欢
        • 2017-03-30
        • 1970-01-01
        • 2018-08-25
        • 2010-12-30
        • 1970-01-01
        • 1970-01-01
        • 2015-04-17
        • 2018-02-01
        • 1970-01-01
        相关资源
        最近更新 更多