3

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

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

我有派生类(和 DerivedB、DerivedC 等),它派生自 Class Base 和一个 ClassLotsOfBases,它包含一个 Virtual Base 向量。

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

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

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

  1. 编译当然没有添加,但是我遇到了运行时问题,因为 Boost 不知道哪个类是哪个......所以我尝试了:

  2. ar.template register_type<Derived>() ;-在“LotsOfBases.h”的序列化函数中注册类Error @ RunTime: what(): Input Stream Error,并在运行时调用时得到以下结果: - 这是我最成功的地方,也是上面主要提到的。

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

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

  5. 我试图在LotsOfBases 反序列化的主目录中使用归档器注册这些类。编译器警告

  6. BOOST_CLASS_EXPORT_IMPLEMENT(TextQuestion)导出类序列化- 与 6 iirc 相同的错误。

  7. 上面没有链接的示例来自我在 StackOverflow 上浏览了大约 30 个页面,这些页面相似,但它们提供的解决方案似乎对我不起作用,或者与 Boost Serialization 有关,但有些无关紧要。

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

班级代码

很多基础:

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

我相信它不应该那么难。所以,我想我的问题是......我做错了什么?我现在应该从哪里开始阅读/研究?

4

1 回答 1

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 实际上并没有继承,这肯定会导致问题。此外,关键点是,如果您在一个类中有一个多态容器,那么您必须在该类中注册每个派生类型(而不是在基类中)。请参阅上面的家庭课程。

希望这对您有所帮助。

于 2015-11-29T05:06:43.300 回答