如何使用boost使用shared_ptr成员序列化对象

时间:2014-11-24 16:58:44

标签: c++ serialization boost deserialization

有抽象的I1和派生的C1

有抽象的I2和派生的C2

I1shared_ptr<I2>。如何使用boost serializaton使它们可序列化?我正在努力做到这一点,但我的应用程序异常。

#include <sstream>
#include <boost/shared_ptr.hpp>
#include <boost/archive/binary_oarchive.hpp>
#include <boost/archive/binary_iarchive.hpp>
#include <boost/serialization/shared_ptr.hpp>

struct I1
{
    I1() {}
    virtual ~I1() = 0 {}

    template<class Archive>
    void serialize(Archive &ar, const unsigned int version)
    {
    }
};

struct C1 : I1
{
    virtual ~C1() {}

    template<class Archive>
    void serialize(Archive &ar, const unsigned int version)
    {
        ar & boost::serialization::base_object<I1>(*this);
    }
};

struct I2
{
    virtual ~I2() = 0 {}

    template<class Archive>
    void serialize(Archive &ar, const unsigned int version)
    {
        ar & p;
    }

    boost::shared_ptr<I1> p;
};

struct C2 : I2
{
    C2() { p = boost::shared_ptr<I1>(new C1); }
    virtual ~C2() { }

    template<class Archive>
    void serialize(Archive &ar, const unsigned int version)
    {
        ar & boost::serialization::base_object<I2>(*this);
    }
};

int main()
{
    C2 c2;

    std::string s;
    std::stringstream ss(s);

    boost::archive::binary_oarchive oa(ss);
    oa.register_type<I1>();
    oa.register_type<C1>();
    oa.register_type<I2>();
    oa.register_type<C2>();

    oa << c2;

    boost::archive::binary_iarchive ia(ss);
    //ia.register_type<I1>(); // cannot instantiate abstract class
    ia.register_type<C1>();
    //ia.register_type<I2>(); // cannot instantiate abstract class
    ia.register_type<C2>();

    ia >> c2;
}

3 个答案:

答案 0 :(得分:3)

boost序列化文档说here有关BOOST_CLASS_EXPORT的有趣内容:

  

...... BOOST_CLASS_EXPORT ...

     

因此,通过使用通过指针或对其基类的引用来操纵的派生类来隐含对导出的需求。

你的p指针就是这样。将这些宏添加到代码中也可以消除来自main的丑陋的显式register_type()调用,这也很好:)

所以,这段代码似乎在VS2014中编译和工作:

#include <sstream>
#include <boost/shared_ptr.hpp>
#include <boost/archive/binary_oarchive.hpp>
#include <boost/archive/binary_iarchive.hpp>
#include <boost/serialization/shared_ptr.hpp>
#include <boost/serialization/export.hpp>

struct I1
{
    I1() {}
    virtual ~I1() = 0 {}

    template<class Archive>
    void serialize(Archive &ar, const unsigned int version)
    {
    }
};

BOOST_CLASS_EXPORT(I1)

struct C1 : I1
{
    virtual ~C1() {}

    template<class Archive>
    void serialize(Archive &ar, const unsigned int version)
    {
        ar & boost::serialization::base_object<I1>(*this);
    }
};

BOOST_CLASS_EXPORT(C1)

struct I2
{
    virtual ~I2() = 0 {}

    template<class Archive>
    void serialize(Archive &ar, const unsigned int version)
    {
        ar & p;
    }

    boost::shared_ptr<I1> p;
};

BOOST_CLASS_EXPORT(I2)

struct C2 : I2
{
    C2() { p = boost::shared_ptr<I1>(new C1); }
    virtual ~C2() { }

    template<class Archive>
    void serialize(Archive &ar, const unsigned int version)
    {
        ar & boost::serialization::base_object<I2>(*this);
    }
};

BOOST_CLASS_EXPORT(C2)

int main()
{
    C2 c2;

    std::string s;
    std::stringstream ss(s);

    boost::archive::binary_oarchive oa(ss);
    oa << c2;

    boost::archive::binary_iarchive ia(ss);
    ia >> c2;
}

有趣的是,Boost文档的声明显然不适用于所有编译器,并且互联网上的大量代码示例在VS2014中不起作用。

答案 1 :(得分:0)

添加

BOOST_SERIALIZATION_ASSUME_ABSTRACT(I1)
BOOST_SERIALIZATION_ASSUME_ABSTRACT(I2)

根据文档http://www.boost.org/doc/libs/1_39_0/libs/serialization/doc/traits.html#abstract

<强>更新

我刚刚使用VS2013RTM和Boost 1_55验证了它,JustWorks(TM),我已经

  • 删除了抽象基础的类型注册(无论如何它们永远不会具体从存档中加载)
  • 加入

    #pragma warning(disable: 4244)
    #include <boost/config/warning_disable.hpp>
    

    在文件的顶部,以沉默已知的健谈警告

编译并运行代码时没有错误。对于好的风格,你应该

以下是我最终的完整代码:

#pragma warning(disable: 4244)
#include <boost/config/warning_disable.hpp>
#include <sstream>
#include <boost/shared_ptr.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/serialization/shared_ptr.hpp>

struct I1
{
    I1() {}
    virtual ~I1() = 0 {}

    template<class Archive>
    void serialize(Archive &ar, const unsigned int version)
    {
    }
};

struct C1 : I1
{
    virtual ~C1() {}

    template<class Archive>
    void serialize(Archive &ar, const unsigned int version)
    {
        ar & boost::serialization::base_object<I1>(*this);
    }
};

struct I2
{
    virtual ~I2() = 0 {}

    template<class Archive>
    void serialize(Archive &ar, const unsigned int version)
    {
        ar & p;
    }

    boost::shared_ptr<I1> p;
};

struct C2 : I2
{
    C2() { p = boost::shared_ptr<I1>(new C1); }
    virtual ~C2() { }

    template<class Archive>
    void serialize(Archive &ar, const unsigned int version)
    {
        ar & boost::serialization::base_object<I2>(*this);
    }
};

int main()
{
    boost::shared_ptr<I2> c2(new C2);

    std::string s;
    std::stringstream ss(s);

    boost::archive::text_oarchive oa(ss);
    oa.register_type<C1>();
    oa.register_type<C2>();

    oa << c2;
    std::cout << "Serialized form: '" << ss.str() << "'\n";

    boost::archive::text_iarchive ia(ss);
    ia.register_type<C1>();
    ia.register_type<C2>();

    ia >> c2;
}

这是输出:

enter image description here

答案 2 :(得分:0)

我认为您不应该在输出存档上注册纯虚拟类。

或者,您可以使用export。定义类后,用以下代码替换其余代码:

#include <boost/serialization/export.hpp>
BOOST_CLASS_EXPORT(C1)
BOOST_CLASS_EXPORT(C2)

int main()
{
    C2 c2;

    std::string s;
    std::stringstream ss(s);

    {
       boost::archive::binary_oarchive oa(ss);
       oa << c2;
    }

    boost::archive::binary_iarchive ia(ss);
    ia >> c2;
}

我将输出存档放入一个单独的块中。我认为它很可能没有它,但我想确保所有内容都被刷新(通过超出范围)。