• 【BOOST C++ 19 应用库】(5)boost::serialization::base_object()


    一、说明

            类层次结构对象的序列化
            派生类必须访问成员函数 serialize() 中的函数 boost::serialization::base_object() 以根据类层次结构序列化对象。该函数保证基类的继承成员变量被正确序列化。

    二、示例和代码

            示例 64.11。正确序列化派生类

    1. #include
    2. #include
    3. #include
    4. #include
    5. using namespace boost::archive;
    6. std::stringstream ss;
    7. class animal
    8. {
    9. public:
    10. animal() = default;
    11. animal(int legs) : legs_{legs} {}
    12. int legs() const { return legs_; }
    13. private:
    14. friend class boost::serialization::access;
    15. template <typename Archive>
    16. void serialize(Archive &ar, const unsigned int version) { ar & legs_; }
    17. int legs_;
    18. };
    19. class bird : public animal
    20. {
    21. public:
    22. bird() = default;
    23. bird(int legs, bool can_fly) :
    24. animal{legs}, can_fly_{can_fly} {}
    25. bool can_fly() const { return can_fly_; }
    26. private:
    27. friend class boost::serialization::access;
    28. template <typename Archive>
    29. void serialize(Archive &ar, const unsigned int version)
    30. {
    31. ar & boost::serialization::base_object(*this);
    32. ar & can_fly_;
    33. }
    34. bool can_fly_;
    35. };
    36. void save()
    37. {
    38. text_oarchive oa{ss};
    39. bird penguin{2, false};
    40. oa << penguin;
    41. }
    42. void load()
    43. {
    44. text_iarchive ia{ss};
    45. bird penguin;
    46. ia >> penguin;
    47. std::cout << penguin.legs() << '\n';
    48. std::cout << std::boolalpha << penguin.can_fly() << '\n';
    49. }
    50. int main()
    51. {
    52. save();
    53. load();
    54. }

    Example 64.11

            示例 64.11 使用了一个名为 bird 的类,它派生自 animal。 animal 和 bird 都定义了一个私有成员函数 serialize() ,这使得序列化基于任一类的对象成为可能。因为 bird 派生自 animal,serialize() 必须确保从 animal 继承的成员变量也被序列化。

            通过在派生类的成员函数 serialize() 中访问基类并调用 boost::serialization::base_object() 来序列化继承的成员变量。您必须使用此函数而不是,例如,static_cast,因为只有 boost::serialization::base_object() 才能确保正确的序列化。

            动态创建对象的地址可以分配给相应基类类型的指针。示例 64.12 表明 Boost.Serialization 也可以正确地序列化它们。

            示例 64.12。使用 BOOST_CLASS_EXPORT 静态注册派生类

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. using namespace boost::archive;
    7. std::stringstream ss;
    8. class animal
    9. {
    10. public:
    11. animal() = default;
    12. animal(int legs) : legs_{legs} {}
    13. virtual int legs() const { return legs_; }
    14. virtual ~animal() = default;
    15. private:
    16. friend class boost::serialization::access;
    17. template <typename Archive>
    18. void serialize(Archive &ar, const unsigned int version) { ar & legs_; }
    19. int legs_;
    20. };
    21. class bird : public animal
    22. {
    23. public:
    24. bird() = default;
    25. bird(int legs, bool can_fly) :
    26. animal{legs}, can_fly_{can_fly} {}
    27. bool can_fly() const { return can_fly_; }
    28. private:
    29. friend class boost::serialization::access;
    30. template <typename Archive>
    31. void serialize(Archive &ar, const unsigned int version)
    32. {
    33. ar & boost::serialization::base_object(*this);
    34. ar & can_fly_;
    35. }
    36. bool can_fly_;
    37. };
    38. BOOST_CLASS_EXPORT(bird)
    39. void save()
    40. {
    41. text_oarchive oa{ss};
    42. animal *a = new bird{2, false};
    43. oa << a;
    44. delete a;
    45. }
    46. void load()
    47. {
    48. text_iarchive ia{ss};
    49. animal *a;
    50. ia >> a;
    51. std::cout << a->legs() << '\n';
    52. delete a;
    53. }
    54. int main()
    55. {
    56. save();
    57. load();
    58. }

            该程序在函数 save() 中创建了一个 bird 类型的对象,并将其分配给一个 animal* 类型的指针,该指针又通过 operator<< 进行序列化。

            上一节提到,被引用的对象被序列化,而不是指针。要让 Boost.Serialization 认识到必须序列化 bird 类型的对象,即使指针是 animal* 类型,也需要声明 bird 类。这是使用在 boost/serialization/export.hpp 中定义的宏 BOOST_CLASS_EXPORT 完成的。因为类型 bird 没有出现在指针定义中,Boost.Serialization 不能在没有宏的情况下正确序列化 bird 类型的对象。

            如果要使用指向相应基类的指针对派生类的对象进行序列化,则必须使用宏 BOOST_CLASS_EXPORT。 BOOST_CLASS_EXPORT 的一个缺点是,由于静态注册,可以注册可能根本不用于序列化的类。 Boost.Serialization 为这种情况提供了解决方案。

            示例 64.13。使用 register_type() 动态注册派生类

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. std::stringstream ss;
    7. class animal
    8. {
    9. public:
    10. animal() = default;
    11. animal(int legs) : legs_{legs} {}
    12. virtual int legs() const { return legs_; }
    13. virtual ~animal() = default;
    14. private:
    15. friend class boost::serialization::access;
    16. template <typename Archive>
    17. void serialize(Archive &ar, const unsigned int version) { ar & legs_; }
    18. int legs_;
    19. };
    20. class bird : public animal
    21. {
    22. public:
    23. bird() = default;
    24. bird(int legs, bool can_fly) :
    25. animal{legs}, can_fly_{can_fly} {}
    26. bool can_fly() const { return can_fly_; }
    27. private:
    28. friend class boost::serialization::access;
    29. template <typename Archive>
    30. void serialize(Archive &ar, const unsigned int version)
    31. {
    32. ar & boost::serialization::base_object(*this);
    33. ar & can_fly_;
    34. }
    35. bool can_fly_;
    36. };
    37. void save()
    38. {
    39. boost::archive::text_oarchive oa{ss};
    40. oa.register_type();
    41. animal *a = new bird{2, false};
    42. oa << a;
    43. delete a;
    44. }
    45. void load()
    46. {
    47. boost::archive::text_iarchive ia{ss};
    48. ia.register_type();
    49. animal *a;
    50. ia >> a;
    51. std::cout << a->legs() << '\n';
    52. delete a;
    53. }
    54. int main()
    55. {
    56. save();
    57. load();
    58. }

            示例 64.13 不使用宏 BOOST_CLASS_EXPORT,而是调用成员函数模板 register_type()。要注册的类型作为模板参数传递。请注意,必须在 save() 和 load() 中调用 register_type()。

            register_type() 的优点是只需要注册用于序列化的类。例如,在开发库时,不知道开发人员以后可能使用哪些类进行序列化。虽然宏 BOOST_CLASS_EXPORT 使这很容易,但它可能会注册不会用于序列化的类型。

  • 相关阅读:
    mysql高手进阶优化篇
    实现动态表单的一种思路 | 京东云技术团队
    5年磨一剑|优酷Android包瘦身治理思路全解
    LeetCode 算法:K 个一组翻转链表 c++
    Taurus .Net Core 微服务开源框架:Admin 插件【4-8】 - 配置管理-Mvc【Plugin-Limit 接口访问限制、IP限制、Ack限制】
    一阶&二阶数字滤波器笔记
    mysql去重distinct
    JavaStringBuffer与StringBuilder
    [springMVC]9、处理json数据(@RequestBody,@ResponseBody)
    FastestDet---模型训练
  • 原文地址:https://blog.csdn.net/gongdiwudu/article/details/128154070