- 11.4. 对象类层次结构的序列化
11.4. 对象类层次结构的序列化
为了序列化基于类层次结构的对象,子类必须在 serialize ()函数中访问 boost::serialization::base_object ()。 此函数确保继承自基类的属性也能正确地序列化。 下面的例子演示了一个名为 developer 类,它继承自类 person 。
- #include <boost/archive/text_oarchive.hpp>
- #include <boost/archive/text_iarchive.hpp>
- #include <boost/serialization/string.hpp>
- #include <iostream>
- #include <sstream>
- #include <string>
- std::stringstream ss;
- class person
- {
- public:
- person()
- {
- }
- person(int age)
- : age_(age)
- {
- }
- int age() const
- {
- return age_;
- }
- private:
- friend class boost::serialization::access;
- template <typename Archive>
- void serialize(Archive &ar, const unsigned int version)
- {
- ar & age_;
- }
- int age_;
- };
- class developer
- : public person
- {
- public:
- developer()
- {
- }
- developer(int age, const std::string &language)
- : person(age), language_(language)
- {
- }
- std::string language() const
- {
- return language_;
- }
- private:
- friend class boost::serialization::access;
- template <typename Archive>
- void serialize(Archive &ar, const unsigned int version)
- {
- ar & boost::serialization::base_object<person>(*this);
- ar & language_;
- }
- std::string language_;
- };
- void save()
- {
- boost::archive::text_oarchive oa(ss);
- developer d(31, "C++");
- oa << d;
- }
- void load()
- {
- boost::archive::text_iarchive ia(ss);
- developer d;
- ia >> d;
- std::cout << d.age() << std::endl;
- std::cout << d.language() << std::endl;
- }
- int main()
- {
- save();
- load();
- }
- 下载源代码
person 和 developer 这两个类都包含有一个私有的 serialize () 函数, 它使得基于其他类的对象能被序列化。 由于 developer 类继承自 person 类, 所以它的 serialize () 函数必须确保继承自 person 属性也能被序列化。
继承自基类的属性被序列化是通过在子类的 serialize () 函数中用 boost::serialization::base_object () 函数访问基类实现的。 在例子中强制要求使用这个函数而不是 static_cast 是因为只有 boost::serialization::base_object () 才能保证正确地序列化。
动态创建对象的地址可以被赋值给对应的基类类型的指针。 下面的例子演示了 Boost.Serialization 还能够正确地序列化它们。
- #include <boost/archive/text_oarchive.hpp>
- #include <boost/archive/text_iarchive.hpp>
- #include <boost/serialization/string.hpp>
- #include <boost/serialization/export.hpp>
- #include <iostream>
- #include <sstream>
- #include <string>
- std::stringstream ss;
- class person
- {
- public:
- person()
- {
- }
- person(int age)
- : age_(age)
- {
- }
- virtual int age() const
- {
- return age_;
- }
- private:
- friend class boost::serialization::access;
- template <typename Archive>
- void serialize(Archive &ar, const unsigned int version)
- {
- ar & age_;
- }
- int age_;
- };
- class developer
- : public person
- {
- public:
- developer()
- {
- }
- developer(int age, const std::string &language)
- : person(age), language_(language)
- {
- }
- std::string language() const
- {
- return language_;
- }
- private:
- friend class boost::serialization::access;
- template <typename Archive>
- void serialize(Archive &ar, const unsigned int version)
- {
- ar & boost::serialization::base_object<person>(*this);
- ar & language_;
- }
- std::string language_;
- };
- BOOST_CLASS_EXPORT(developer)
- void save()
- {
- boost::archive::text_oarchive oa(ss);
- person *p = new developer(31, "C++");
- oa << p;
- delete p;
- }
- void load()
- {
- boost::archive::text_iarchive ia(ss);
- person *p;
- ia >> p;
- std::cout << p->age() << std::endl;
- delete p;
- }
- int main()
- {
- save();
- load();
- }
- 下载源代码
应用程序在 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 为这种情况提供一种解决方案。
- #include <boost/archive/text_oarchive.hpp>
- #include <boost/archive/text_iarchive.hpp>
- #include <boost/serialization/string.hpp>
- #include <boost/serialization/export.hpp>
- #include <iostream>
- #include <sstream>
- #include <string>
- std::stringstream ss;
- class person
- {
- public:
- person()
- {
- }
- person(int age)
- : age_(age)
- {
- }
- virtual int age() const
- {
- return age_;
- }
- private:
- friend class boost::serialization::access;
- template <typename Archive>
- void serialize(Archive &ar, const unsigned int version)
- {
- ar & age_;
- }
- int age_;
- };
- class developer
- : public person
- {
- public:
- developer()
- {
- }
- developer(int age, const std::string &language)
- : person(age), language_(language)
- {
- }
- std::string language() const
- {
- return language_;
- }
- private:
- friend class boost::serialization::access;
- template <typename Archive>
- void serialize(Archive &ar, const unsigned int version)
- {
- ar & boost::serialization::base_object<person>(*this);
- ar & language_;
- }
- std::string language_;
- };
- void save()
- {
- boost::archive::text_oarchive oa(ss);
- oa.register_type<developer>();
- person *p = new developer(31, "C++");
- oa << p;
- delete p;
- }
- void load()
- {
- boost::archive::text_iarchive ia(ss);
- ia.register_type<developer>();
- person *p;
- ia >> p;
- std::cout << p->age() << std::endl;
- delete p;
- }
- int main()
- {
- save();
- load();
- }
- 下载源代码
上面的应用程序没有使用 BOOST_CLASS_EXPORT 宏,而是调用了 register_type () 模板函数。 需要注册的类型作为模板参数传入。
请注意 register_type () 必须在 save () 和 load () 都要调用。
register_type () 的优点是只有需要序列化的类才注册。 比如在开发一个库时,你不知道开发人员将来要序列化哪些类。 当然 BOOST_CLASS_EXPORT 宏用起来简单,可它却可能注册那些不需要序列化的类型。
