如何序列化/反序列化继承无默认构造函数基类的派生类?
实现继承无默认构造函数基类的派生类Boost序列化
当类包含const成员且无默认构造函数时,Boost常规的赋值式序列化无法工作,必须通过序列化构造参数的方式来创建对象并初始化成员。以下是针对你的Base和Derived类的完整实现方案:
#include <boost/serialization/access.hpp> #include <boost/serialization/nvp.hpp> #include <boost/archive/text_oarchive.hpp> #include <boost/archive/text_iarchive.hpp> #include <iostream> #include <sstream> struct Base { Base(int b) : b(b) {} const int b; // 允许Boost序列化框架访问类内部 friend class boost::serialization::access; // 序列化函数(仅声明,实际通过构造数据函数处理初始化) template<class Archive> void serialize(Archive& ar, const unsigned int version) { // const成员通过构造初始化,此处无需操作 } }; // 保存Base的构造参数 template<class Archive> void save_construct_data(Archive& ar, const Base* obj, const unsigned int version) { ar << BOOST_SERIALIZATION_NVP(obj->b); } // 加载Base的构造参数并构造对象 template<class Archive> void load_construct_data(Archive& ar, Base* obj, const unsigned int version) { int b; ar >> BOOST_SERIALIZATION_NVP(b); // 使用placement new在指定内存构造Base对象 ::new(obj) Base(b); } struct Derived : public Base { Derived(float d, int b) : Base(b), d(d) {} const float d; friend class boost::serialization::access; template<class Archive> void serialize(Archive& ar, const unsigned int version) { // 触发基类的序列化逻辑 ar & boost::serialization::base_object<Base>(*this); } }; // 保存Derived的构造参数(先处理基类,再处理自身) template<class Archive> void save_construct_data(Archive& ar, const Derived* obj, const unsigned int version) { save_construct_data(ar, static_cast<const Base*>(obj), version); ar << BOOST_SERIALIZATION_NVP(obj->d); } // 加载Derived的构造参数并构造对象 template<class Archive> void load_construct_data(Archive& ar, Derived* obj, const unsigned int version) { int b; float d; ar >> BOOST_SERIALIZATION_NVP(b); ar >> BOOST_SERIALIZATION_NVP(d); ::new(obj) Derived(d, b); } // 测试序列化与反序列化流程 int main() { Derived original(3.14f, 42); // 序列化到字符串流 std::stringstream ss; boost::archive::text_oarchive oa(ss); oa << original; // 反序列化 Derived* restored = nullptr; boost::archive::text_iarchive ia(ss); ia >> restored; // 验证结果 std::cout << "Original: b=" << original.b << ", d=" << original.d << std::endl; std::cout << "Restored: b=" << restored->b << ", d=" << restored->d << std::endl; delete restored; return 0; }
核心要点说明
- 构造数据序列化:通过
save_construct_data和load_construct_data函数,专门处理类构造参数的保存与加载,再借助placement new直接在反序列化内存中构造对象,规避了对const成员的赋值操作。 - 基类优先处理:派生类的构造数据序列化必须先完成基类参数的处理,确保继承层次的初始化顺序正确。
- 权限声明:每个类需添加
friend class boost::serialization::access;,让序列化框架能够访问类的内部成员。
内容的提问来源于stack exchange,提问作者yukkute
相关产品推荐
相关产品推荐

