• 11.4. 对象类层次结构的序列化

    11.4. 对象类层次结构的序列化

    为了序列化基于类层次结构的对象,子类必须在 serialize ()函数中访问 boost::serialization::base_object ()。 此函数确保继承自基类的属性也能正确地序列化。 下面的例子演示了一个名为 developer 类,它继承自类 person

    1. #include <boost/archive/text_oarchive.hpp>
    2. #include <boost/archive/text_iarchive.hpp>
    3. #include <boost/serialization/string.hpp>
    4. #include <iostream>
    5. #include <sstream>
    6. #include <string>
    7.  
    8. std::stringstream ss;
    9.  
    10. class person
    11. {
    12. public:
    13. person()
    14. {
    15. }
    16.  
    17. person(int age)
    18. : age_(age)
    19. {
    20. }
    21.  
    22. int age() const
    23. {
    24. return age_;
    25. }
    26.  
    27. private:
    28. friend class boost::serialization::access;
    29.  
    30. template <typename Archive>
    31. void serialize(Archive &ar, const unsigned int version)
    32. {
    33. ar & age_;
    34. }
    35.  
    36. int age_;
    37. };
    38.  
    39. class developer
    40. : public person
    41. {
    42. public:
    43. developer()
    44. {
    45. }
    46.  
    47. developer(int age, const std::string &language)
    48. : person(age), language_(language)
    49. {
    50. }
    51.  
    52. std::string language() const
    53. {
    54. return language_;
    55. }
    56.  
    57. private:
    58. friend class boost::serialization::access;
    59.  
    60. template <typename Archive>
    61. void serialize(Archive &ar, const unsigned int version)
    62. {
    63. ar & boost::serialization::base_object<person>(*this);
    64. ar & language_;
    65. }
    66.  
    67. std::string language_;
    68. };
    69.  
    70. void save()
    71. {
    72. boost::archive::text_oarchive oa(ss);
    73. developer d(31, "C++");
    74. oa << d;
    75. }
    76.  
    77. void load()
    78. {
    79. boost::archive::text_iarchive ia(ss);
    80. developer d;
    81. ia >> d;
    82. std::cout << d.age() << std::endl;
    83. std::cout << d.language() << std::endl;
    84. }
    85.  
    86. int main()
    87. {
    88. save();
    89. load();
    90. }
    91.  
    • 下载源代码

    person developer 这两个类都包含有一个私有的 serialize () 函数, 它使得基于其他类的对象能被序列化。 由于 developer 类继承自 person 类, 所以它的 serialize () 函数必须确保继承自 person 属性也能被序列化。

    继承自基类的属性被序列化是通过在子类的 serialize () 函数中用 boost::serialization::base_object () 函数访问基类实现的。 在例子中强制要求使用这个函数而不是 static_cast 是因为只有 boost::serialization::base_object () 才能保证正确地序列化。

    动态创建对象的地址可以被赋值给对应的基类类型的指针。 下面的例子演示了 Boost.Serialization 还能够正确地序列化它们。

    1. #include <boost/archive/text_oarchive.hpp>
    2. #include <boost/archive/text_iarchive.hpp>
    3. #include <boost/serialization/string.hpp>
    4. #include <boost/serialization/export.hpp>
    5. #include <iostream>
    6. #include <sstream>
    7. #include <string>
    8.  
    9. std::stringstream ss;
    10.  
    11. class person
    12. {
    13. public:
    14. person()
    15. {
    16. }
    17.  
    18. person(int age)
    19. : age_(age)
    20. {
    21. }
    22.  
    23. virtual int age() const
    24. {
    25. return age_;
    26. }
    27.  
    28. private:
    29. friend class boost::serialization::access;
    30.  
    31. template <typename Archive>
    32. void serialize(Archive &ar, const unsigned int version)
    33. {
    34. ar & age_;
    35. }
    36.  
    37. int age_;
    38. };
    39.  
    40. class developer
    41. : public person
    42. {
    43. public:
    44. developer()
    45. {
    46. }
    47.  
    48. developer(int age, const std::string &language)
    49. : person(age), language_(language)
    50. {
    51. }
    52.  
    53. std::string language() const
    54. {
    55. return language_;
    56. }
    57.  
    58. private:
    59. friend class boost::serialization::access;
    60.  
    61. template <typename Archive>
    62. void serialize(Archive &ar, const unsigned int version)
    63. {
    64. ar & boost::serialization::base_object<person>(*this);
    65. ar & language_;
    66. }
    67.  
    68. std::string language_;
    69. };
    70.  
    71. BOOST_CLASS_EXPORT(developer)
    72.  
    73. void save()
    74. {
    75. boost::archive::text_oarchive oa(ss);
    76. person *p = new developer(31, "C++");
    77. oa << p;
    78. delete p;
    79. }
    80.  
    81. void load()
    82. {
    83. boost::archive::text_iarchive ia(ss);
    84. person *p;
    85. ia >> p;
    86. std::cout << p->age() << std::endl;
    87. delete p;
    88. }
    89.  
    90. int main()
    91. {
    92. save();
    93. load();
    94. }
    95.  
    • 下载源代码

    应用程序在 save () 函数创建了 developer 类型的对象并赋值给 person* 类型的指针,接下来通过 << 序列化。

    正如在前面章节中提到的, 引用对象被自动地序列化。 为了让 Boost.Serialization 识别将要序列化的 developer 类型的对象,即使指针是 person* 类型的对象。 developer 类需要相应的声明。 这是通过这个 BOOST_CLASS_EXPORT 宏实现的,它定义在 boost/serialization/export.hpp 文件中。 因为 developer 这个数据类型没有指针形式的定义,所以 Boost.Serialization 没有这个宏就不能正确地序列化 developer

    如果子类对象需要通过基类的指针序列化,那么 BOOST_CLASS_EXPORT 宏必须要用。

    由于静态注册的原因, BOOST_CLASS_EXPORT 的一个缺点是可能有些注册的类最后是不需要序列化的。 Boost.Serialization 为这种情况提供一种解决方案。

    1. #include <boost/archive/text_oarchive.hpp>
    2. #include <boost/archive/text_iarchive.hpp>
    3. #include <boost/serialization/string.hpp>
    4. #include <boost/serialization/export.hpp>
    5. #include <iostream>
    6. #include <sstream>
    7. #include <string>
    8.  
    9. std::stringstream ss;
    10.  
    11. class person
    12. {
    13. public:
    14. person()
    15. {
    16. }
    17.  
    18. person(int age)
    19. : age_(age)
    20. {
    21. }
    22.  
    23. virtual int age() const
    24. {
    25. return age_;
    26. }
    27.  
    28. private:
    29. friend class boost::serialization::access;
    30.  
    31. template <typename Archive>
    32. void serialize(Archive &ar, const unsigned int version)
    33. {
    34. ar & age_;
    35. }
    36.  
    37. int age_;
    38. };
    39.  
    40. class developer
    41. : public person
    42. {
    43. public:
    44. developer()
    45. {
    46. }
    47.  
    48. developer(int age, const std::string &language)
    49. : person(age), language_(language)
    50. {
    51. }
    52.  
    53. std::string language() const
    54. {
    55. return language_;
    56. }
    57.  
    58. private:
    59. friend class boost::serialization::access;
    60.  
    61. template <typename Archive>
    62. void serialize(Archive &ar, const unsigned int version)
    63. {
    64. ar & boost::serialization::base_object<person>(*this);
    65. ar & language_;
    66. }
    67.  
    68. std::string language_;
    69. };
    70.  
    71. void save()
    72. {
    73. boost::archive::text_oarchive oa(ss);
    74. oa.register_type<developer>();
    75. person *p = new developer(31, "C++");
    76. oa << p;
    77. delete p;
    78. }
    79.  
    80. void load()
    81. {
    82. boost::archive::text_iarchive ia(ss);
    83. ia.register_type<developer>();
    84. person *p;
    85. ia >> p;
    86. std::cout << p->age() << std::endl;
    87. delete p;
    88. }
    89.  
    90. int main()
    91. {
    92. save();
    93. load();
    94. }
    95.  
    • 下载源代码

    上面的应用程序没有使用 BOOST_CLASS_EXPORT 宏,而是调用了 register_type () 模板函数。 需要注册的类型作为模板参数传入。

    请注意 register_type () 必须在 save ()load () 都要调用。

    register_type () 的优点是只有需要序列化的类才注册。 比如在开发一个库时,你不知道开发人员将来要序列化哪些类。 当然 BOOST_CLASS_EXPORT 宏用起来简单,可它却可能注册那些不需要序列化的类型。