2013-07-17 75 views
3

我試圖(去)序列化多態向量,但有不同的嘗試不同的問題。事件的整個順序是:多態序列化w/boost

  • 序列化一個多態矢量在服務器端
  • 發送序列化的字符串通過網絡
  • 反序列化到一個新的多態矢量在客戶端
  • 編輯數據中客戶端向量(包括添加,編輯和刪除)
  • 在客戶端序列化已編輯的多態向量
  • 通過網絡發送新的序列化字符串
  • 反序列化新的多態矢量在服務器端< --- 這是我的問題在於

我已經派生類(和DerivedB,DerivedC等),其從階級基礎派生&一類LotsOfBases其中包含一個虛擬基地矢量。

雖然我不明白這可能是怎麼導致這個問題 - 我相信我的問題是因爲來自服務器的Vector中的對象按照特定的順序(AAABBCCCCD),當它們回來時它們處於一個隨機的順序,並可能有不同數量的派生類(ABABCDDDA)。

以下是我的失敗嘗試。使用下面的方法2,如果我是幸運我可以來回發送信息(如果類順序保持不變),但是當類類型更改順序時,問題開始出現。

代碼中使用&編譯/運行時錯誤:

  1. 沒有當然的增加編譯,但我得到的運行時問題作爲升壓不知道哪個類是......所以,我想:

  2. ar.template register_type<Derived>() ; - Registering Class在「LotsOfBases.h」的序列化功能,並得到了當在運行時調用如下:Error @ RunTime: what(): Input Stream Error - 這是我有最大的成功,什麼是主要如上所述。

  3. ar.register_type<static...,但我得到的編譯錯誤,說明其功能(見要不然這地方在計算器上

  4. BOOST_CLASS_EXPORT(Derived) ;在「.H」文件,該文件提供了ñ警告爲每個不同的子類的結尾基地和無法編譯錯誤:。multiple definition of ``boost::archive::detail::extra_detail::init_guid<Derived>::g'

  5. 我試圖與主歸檔登記類,其中LotsOfBases得到Deserialised編譯器警告

  6. BOOST_CLASS_EXPORT_IMPLEMENT(TextQuestion) from Exporting Class Serialization - 與6 iirc相同的錯誤。

  7. 上面沒有鏈接的例子來自我在StackOverflow上通過大約30頁的介紹,它們很相似,但是它們提供的解決方案似乎不適合我,或者與Boost Serialization相關,但有點不相關。

以下是我的代碼縮短版本(沒有編輯從其它地方使用的):

類代碼

LotsOfBases:

#include "s11n.h" //Import All Serialization Headers In Correct Order 
namespace boost { namespace serialization { class access ; } } 

class LotsOfBases 
{ 
    public: 
    std::vector<Base *> getAllBases() ; 
    protected: 
    std::vector<Base *> allBases() ; 

    friend class boost::serialization::access ; 

    template <typename Archive> 
    void serialize(Archive& ar, const unsigned int /*version*/) 
    { 
     ar & allBases ; 
    } 

} ; 

基地:

#include "s11n.h" //Import All Serialization Headers In Correct Order 
namespace boost { namespace serialization { class access ; } } 

class Base 
{ 
    public: 
    Base() ; 
    ~Base() ; 

    virtual std::string getBaseLocation() ; 
    protected: 
    std::string baseLocation ; 

    friend class boost::serialization::access ; 

    template <typename Archive> 
    void serialize(Archive& ar, const unsigned int /*version*/) 
    { 
     ar & baseLocation ; 
    } 
} ; 

衍生

#include "s11n.h" //Import All Serialization Headers In Correct Order 
namespace boost { namespace serialization { class access ; } } 

class Derived 
{ 
    public: 
    Derived() ; 

    bool getIsAttackableBase() ; 
    private: 
    bool isAttackableBase ; 

    typedef Base _super; 
    friend class boost::serialization::access ; 

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

我敢肯定,這不應該是那麼困難。所以,我想我的問題是......我做錯了什麼?我現在應該從哪裏開始閱讀/研究?

+1

無法在包含文件中指定BOOST_CLASS_EXPORT。這在文檔中沒有反映出來! (坦率地說,boost文檔很糟糕,boost :: serialize文檔很糟糕)。嘗試將其移至實施文件。你可以詳細說明BOOST_CLASS_EXPORT_KEY/BOOST_CLASS_EXPORT_IMPLEMENT嗎?你究竟做了什麼,什麼不起作用? –

+0

另外我希望這不是你真正的代碼(沒有虛擬析構函數,Derived不會繼承Base。) –

回答

3

我和你一樣,在如何序列化一個多態數據方面搜索了相當長的一段時間,而且你的問題足以提供足夠的信息來幫助我理解錯誤並糾正你的錯誤。由於你的類沒有完全實現,我提供了一個實現你想要的代碼示例。在我的例子

#pragma once 
#include <iostream> 
#include <vector> 
#include <boost/archive/binary_oarchive.hpp> 
#include <boost/archive/binary_iarchive.hpp> 
#include <boost/serialization/vector.hpp> 
#include <boost/serialization/string.hpp> 
#include <boost/serialization/base_object.hpp> 
#include <boost/iostreams/device/back_inserter.hpp> 
#include <boost/iostreams/stream.hpp> 

using namespace std; 
class Parent; // Forward declares 
class Child; // so my classes are in your order 

家庭是你LotsOfBases

class Family { 

    friend class boost::serialization::access; 

public: 
    Family() { ; } 
    ~Family() { ; } 

    vector<Parent*> m_members; 
    ////////////////////////////////////////////////////////////////////// 
    template<class Archive> 
    void serialize(Archive & ar, const unsigned int version) 
    { 
     ar.template register_type<Child>(); 
     ar & m_members; 
    } 
    ////////////////////////////////////////////////////////////////////// 

}; 

家長是你基地

class Parent { 

    friend class boost::serialization::access; 

public: 
    Parent() : m_name("") { ; } 
    Parent(string name) : m_name(name) { ; } 
    ~Parent() { ; } 

    virtual string GetName() { return m_name; } 
private: 

    string m_name; 

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

兒童是你的衍生

class Child : public Parent { 

    friend class boost::serialization::access; 

public: 
    Child() : Parent(), m_age(0) { ; } 
    Child(string name, int id) : Parent(name), m_age(id) { ; } 
    ~Child() { ; } 
    int m_age; 
private: 
    ////////////////////////////////////////////////////////////////////// 
    template<class Archive> 
    void serialize(Archive & ar, const unsigned int version) 
    { 
     ar & boost::serialization::base_object<Parent>(*this); 
     ar & m_age; 
    } 
    ////////////////////////////////////////////////////////////////////// 
}; 

主要(出於完整性)

int main() { 

    Child *timmy = new Child("Timmy", 4); 
    Family JohnsonFamily; 
    JohnsonFamily.m_members.push_back(timmy); 

    // serialize object into a std::string 
    std::string serial_str; 
    boost::iostreams::back_insert_device<std::string> inserter(serial_str); 
    boost::iostreams::stream<boost::iostreams::back_insert_device<std::string>> s(inserter); 
    boost::archive::binary_oarchive oa(s); 

    oa & JohnsonFamily; 
    s.flush(); 

    // read object backout of standard string into new Family object 
    boost::iostreams::basic_array_source<char> device(serial_str.data(), serial_str.size()); 
    boost::iostreams::stream<boost::iostreams::basic_array_source<char> > t(device); 
    boost::archive::binary_iarchive ia(t); 

    Family FosterFamily; 
    ia & FosterFamily; 

    auto baseptr = FosterFamily.m_members[0]; 
    auto child = dynamic_cast<Child*>(baseptr); 
    if (child != nullptr) { 
     cout << "Derived type infered from serialized base pointer." << endl; 
     cout << child->GetName() << " is " << child->m_age << endl; 
    } 

    cin.get(); 
    return 0; 
} 

我注意到,你的派生實際上並沒有繼承,這當然引起的問題。另外,關鍵是如果你在一個類中有一個多態容器,那麼你必須在那個類中註冊每個派生類型(不在基類中)。見上面我的家庭課。

希望這可以幫助你。