具有Boost的多态序列化

时间:2013-07-17 11:12:07

标签: c++ serialization boost boost-serialization

我正在尝试(de)序列化多态矢量,但在不同的尝试中存在不同的问题。事件的整个顺序是:

  • 在服务器端序列化多态矢量
  • 通过网络发送序列化字符串
  • 在客户端反序列化为新的多态矢量
  • 在客户端编辑向量中的数据(包括添加,编辑和删除)
  • 在客户端序列化已编辑的多态矢量
  • 通过网络发送新的序列化字符串
  • 在服务器端反序列化新的多态矢量< --- 这就是我的问题所在

我有Class Derived(和DerivedB,DerivedC等),它派生自Class Base&一个类LotsOfBases,它包含一个虚拟基础向量。

虽然,我不知道这是如何导致这个问题的 - 我相信我的问题是因为来自服务器的Vector中的对象是按特定顺序(AAABBCCCCD),当他们回来时他们在随机顺序,可能有不同数量的派生类(ABABCDDDA)。

以下是我失败的尝试。使用下面的方法2,如果我幸运我可以来回发送信息(如果课程顺序保持不变),但是当课程类型改变顺序时,问题就会开始发生。

代码使用&编译/运行时错误:

  1. 编译时没有添加任何内容,但我得到了RunTime问题,因为Boost不知道哪个类是哪个...所以我试过了:

  2. “LotsOfBases.h”的序列化函数中的
  3. ar.template register_type<Derived>() ; - Registering Class在RunTime调用时得到以下内容:Error @ RunTime: what(): Input Stream Error - 这是我最常用的地方成功和上面主要提到的内容。

  4. ar.register_type<static...但是我收到编译错误,说明了它的一个函数(在StackOverflow上看到了其他地方

  5. BOOST_CLASS_EXPORT(Derived) ;在“.h”文件的末尾,它为每个不同的Base子类提供 n 警告,并且无法编译。错误:multiple definition of ``boost::archive::detail::extra_detail::init_guid<Derived>::g'

  6. 我尝试在LotsOfBases进行反序列化的主要寄存器中注册类。编译器警告

  7. 来自Exporting Class Serialization
  8. BOOST_CLASS_EXPORT_IMPLEMENT(TextQuestion) - 与6 iirc相同的错误。

  9. 上面没有链接的例子来自我在StackOverflow上的大约30个页面,这些页面相似,但是他们提供的解决方案对我来说似乎不起作用,或者与Boost序列化有关,但有些不相关。

  10. 以下是我的代码的缩写版本(没有从其他地方使用的编辑):

    课程代码

    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 个答案:

答案 0 :(得分: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;
}

我注意到你的Derived实际上并没有继承,这肯定会导致问题。此外,关键是如果类中有多态容器,则必须在该类中注册每个派生类型(而不是在基类中)。请参阅上面的我的家庭课。

希望这会对你有所帮助。

相关问题