2014-11-24 62 views
3

有抽象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

回答

3

升壓序列化文檔說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

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

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

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; 
} 

我把輸出檔案放到一個單獨的塊中。我認爲它最有可能沒有它,但我想確保一切都被刷新(通過超出範圍)。

+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

相關問題