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

问题描述:

有抽象I1和派生C1如何使用boost序列化与shared_ptr成员的对象

有摘要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; 
} 
+0

你能告诉我们哪个编译器接受'= 0 {}'语法吗?我知道它存在,但我不知道接受此输入的编译器 – sehe 2014-11-25 12:17:48

+0

我使用MSVC编译器 – Ufx 2014-11-26 18:33:17

+0

有趣的是,您的代码在Linux上的gcc 4.8.1上运行正常(除了'= 0 {}'语法)。 – 2014-11-27 11:45:29

升压序列化文档说hereBOOST_CLASS_EXPORT有趣的事情:

... ... BOOST_CLASS_EXPORT

因此,需要导出是通过使用通过指针或对其基类的引用操作的派生类来使用的。

您的p指针确实如此。添加这些宏代码也摆脱从你的主丑明确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中不起作用。

+0

我实际上在虚拟机中安装了VS2014来试试这个,因为通过这种方式序列化共享指针只需要工作:) – 2014-11-27 14:00:14

+0

非常感谢! 。 – Ufx 2014-11-27 14:34:25

添加

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

UPDATE

我刚刚验证与VS2013RTM和Boost 1_55,它JustWorks(TM),我ve

  • 除去抽象碱基类型注册(它们永远不能具体从反正存档加载
  • 在沉默文件的顶部加入

    #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

+0

他们在哪里需要添加? – Ufx 2014-11-25 03:27:27

+0

我只是在界面类声明后立即添加它们 – sehe 2014-11-25 10:09:02

+0

对我没有帮助。 – Ufx 2014-11-25 12:16:59

我认为你不应该在输出存档上注册你的纯虚拟类。可以使用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; 
} 

我把输出档案放到一个单独的块中。我认为它最有可能没有它,但我想确保一切都被刷新(通过超出范围)。

+0

没有帮助我。对你起作用吗?我使用MSVC12。 – Ufx 2014-11-26 15:51:23

+0

它在叮当声和gcc上对我有用。你是否尝试过两种方法(删除抽象类的register_type,用上面的代码替换main)?什么错误,同一个? – rhashimoto 2014-11-26 15:57:54

+0

我觉得错误是一样的。 archive_exception(archive_exception :: unregistered_class)“未注册的类”。调用堆栈:http://pastebin.com/wU7ARa4F – Ufx 2014-11-26 16:30:49