Serialization 增强序列化和指向父类的指针

Serialization 增强序列化和指向父类的指针,serialization,boost,Serialization,Boost,假设以下简化代码: 父类 #include <boost/archive/text_oarchive.hpp> #include <boost/archive/text_iarchive.hpp> #include <boost/serialization/unique_ptr.hpp> class Parent { public: Parent(); ... priva

假设以下简化代码:

父类

    #include <boost/archive/text_oarchive.hpp>
    #include <boost/archive/text_iarchive.hpp>
    #include <boost/serialization/unique_ptr.hpp>

    class Parent
    {
    public:
        Parent();
        ...
    private:
        // boost serialization
        friend class boost::serialization::access;
        template<class Archive>
        void serialize(Archive & ar, const unsigned int version)
        {
            ar & *m_child;
        }

        std::unique_ptr<Child> m_child;
    }

    Parent::Parent()
    {
        ...
        m_child = std::unique_ptr<Child>(new Child(this));
    }
    #include <boost/archive/text_oarchive.hpp>
    #include <boost/archive/text_iarchive.hpp>
    #include <boost/serialization/unique_ptr.hpp>

    class Child
    {
    public:
        Child(Parent * parent)
        {
            m_parent = parent;
        };
        ...
    private:
        // boost serialization
        friend class boost::serialization::access;
        template<class Archive>
        void serialize(Archive & ar, const unsigned int version)
        {
            ar & m_parent;
        }
        Child(){};

        Parent m_parent{ nullptr };
    }
#包括
#包括
#包括
班级家长
{
公众:
父项();
...
私人:
//推进序列化
好友类boost::serialization::access;
模板
无效序列化(存档和ar,常量未签名整数版本)
{
ar&mèu child;
}
std::唯一的\u ptr m_child;
}
父::父()
{
...
m_child=std::unique_ptr(新子(this));
}
儿童班

    #include <boost/archive/text_oarchive.hpp>
    #include <boost/archive/text_iarchive.hpp>
    #include <boost/serialization/unique_ptr.hpp>

    class Parent
    {
    public:
        Parent();
        ...
    private:
        // boost serialization
        friend class boost::serialization::access;
        template<class Archive>
        void serialize(Archive & ar, const unsigned int version)
        {
            ar & *m_child;
        }

        std::unique_ptr<Child> m_child;
    }

    Parent::Parent()
    {
        ...
        m_child = std::unique_ptr<Child>(new Child(this));
    }
    #include <boost/archive/text_oarchive.hpp>
    #include <boost/archive/text_iarchive.hpp>
    #include <boost/serialization/unique_ptr.hpp>

    class Child
    {
    public:
        Child(Parent * parent)
        {
            m_parent = parent;
        };
        ...
    private:
        // boost serialization
        friend class boost::serialization::access;
        template<class Archive>
        void serialize(Archive & ar, const unsigned int version)
        {
            ar & m_parent;
        }
        Child(){};

        Parent m_parent{ nullptr };
    }
#包括
#包括
#包括
班童
{
公众:
子(父*父)
{
m_parent=父母;
};
...
私人:
//推进序列化
好友类boost::serialization::access;
模板
无效序列化(存档和ar,常量未签名整数版本)
{
ar&m_母公司;
}
Child(){};
父m_父{nullptr};
}
我的父类创建一个子类,并传递一个指向子类存储的自身的指针。 在归档父类时,它归档子类,该子类归档指向父类的指针。 还原父类时,它会创建子类并将其还原。我的问题是:

子类中的指针是否能够正确还原,从而保证指向其父类

我通过单步调试并将父级的This指针的值与子级的m_父级的值进行比较,验证了这一点。然而,我不知道boost是如何做到这一点的,这让我怀疑自己是否只是“走运”。有人能验证boost序列化是否足够聪明,可以维护child::m_parent->parent关系吗

或者我应该采取额外的步骤,不存档指针并在加载对象后设置它吗?

两件事:

  • 促进了这一点。序列化指针时,默认情况下启用对象跟踪

  • 不,您不会像那样序列化
    唯一\u ptr

事实上,也没有什么理由序列化子级的
m_父级
,因为父级可以从加载处理程序中设置自引用

但假设您想要简单的方法,让我们坚持这个想法,并使其工作,由于目标跟踪

演示 我包括了一些技巧来演示反序列化

  • 更正指向同一对象的重复数据消除指针
  • 即使在反序列化之前强制“中断”不变量,也会恢复成员指针

#include <boost/archive/text_iarchive.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/serialization/unique_ptr.hpp>
#include <memory>
#include <sstream>
#include <iostream>

class Parent;

class Child {
  public:
    Child(Parent *parent) 
        : m_parent(parent), m_duplicate_parent(parent) {}

    Parent *m_parent          { nullptr };
    Parent *m_duplicate_parent{ nullptr };
  private:
    friend class boost::serialization::access;
    template <class Archive> void serialize(Archive &ar, unsigned) {
        ar & m_parent & m_duplicate_parent; 
    }

    Child() = default;
};

class Parent {
  public:
    Parent() : m_child(std::make_unique<Child>(this)) {}

  //private:
    friend class boost::serialization::access;
    template <class Archive> void serialize(Archive &ar, unsigned) {
        ar & m_child; 
    }

    std::unique_ptr<Child> m_child;
};

int main() {
    std::stringstream ss;
    {
        boost::archive::text_oarchive oa(ss);

        Parent p;
        assert(&p == p.m_child->m_parent);
        assert(&p == p.m_child->m_duplicate_parent);
        oa << p;
    }

    std::cout << ss.str();

    {
        boost::archive::text_iarchive ia(ss);

        Parent p;
        // let's purposelly break the invariants so we know deserialization
        // does restore them as required, and we not just "getting lucky":
        p.m_child->m_parent = nullptr;
        p.m_child->m_duplicate_parent = nullptr;
        assert(&p != p.m_child->m_parent);
        assert(&p != p.m_child->m_duplicate_parent);

        // nuclear:
        p.m_child.reset();

        // now deserialize
        ia >> p;

        assert(&p == p.m_child->m_parent);
        assert(&p == p.m_child->m_duplicate_parent);
    }
}
两件事:

  • 促进了这一点。序列化指针时,默认情况下启用对象跟踪

  • 不,您不会像那样序列化
    唯一\u ptr

事实上,也没有什么理由序列化子级的
m_父级
,因为父级可以从加载处理程序中设置自引用

但假设您想要简单的方法,让我们坚持这个想法,并使其工作,由于目标跟踪

演示 我包括了一些技巧来演示反序列化

  • 更正指向同一对象的重复数据消除指针
  • 即使在反序列化之前强制“中断”不变量,也会恢复成员指针

#include <boost/archive/text_iarchive.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/serialization/unique_ptr.hpp>
#include <memory>
#include <sstream>
#include <iostream>

class Parent;

class Child {
  public:
    Child(Parent *parent) 
        : m_parent(parent), m_duplicate_parent(parent) {}

    Parent *m_parent          { nullptr };
    Parent *m_duplicate_parent{ nullptr };
  private:
    friend class boost::serialization::access;
    template <class Archive> void serialize(Archive &ar, unsigned) {
        ar & m_parent & m_duplicate_parent; 
    }

    Child() = default;
};

class Parent {
  public:
    Parent() : m_child(std::make_unique<Child>(this)) {}

  //private:
    friend class boost::serialization::access;
    template <class Archive> void serialize(Archive &ar, unsigned) {
        ar & m_child; 
    }

    std::unique_ptr<Child> m_child;
};

int main() {
    std::stringstream ss;
    {
        boost::archive::text_oarchive oa(ss);

        Parent p;
        assert(&p == p.m_child->m_parent);
        assert(&p == p.m_child->m_duplicate_parent);
        oa << p;
    }

    std::cout << ss.str();

    {
        boost::archive::text_iarchive ia(ss);

        Parent p;
        // let's purposelly break the invariants so we know deserialization
        // does restore them as required, and we not just "getting lucky":
        p.m_child->m_parent = nullptr;
        p.m_child->m_duplicate_parent = nullptr;
        assert(&p != p.m_child->m_parent);
        assert(&p != p.m_child->m_duplicate_parent);

        // nuclear:
        p.m_child.reset();

        // now deserialize
        ia >> p;

        assert(&p == p.m_child->m_parent);
        assert(&p == p.m_child->m_duplicate_parent);
    }
}

对不起,输入错误,应该是:Parent*m_Parent{nullptr};对不起,输入错误,应该是:Parent*m_Parent{nullptr};