You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何序列化/反序列化继承无默认构造函数基类的派生类?

实现继承无默认构造函数基类的派生类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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 08:45:39