使用Boost反序列化一个指向派生类的问题:序列化 [英] Problems deserializing a pointer to a derived class using Boost:serialize

查看:840
本文介绍了使用Boost反序列化一个指向派生类的问题:序列化的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个奇怪的问题,试图指向反序列化与升压序列化派生类。我有一个基地,每个我尝试反序列化的指针我得到的不是输入流的错误异常或未注册类异常时他们外面SAVE / LOAD功能(非侵入性的版本),但而得。这是我做的:

I have a weird problem trying to deserialize a pointer to a derived class with boost serialize. I have a base and derived with save/load function outside them (non intrusive version) but each time I try to deserialize a pointer I get either "Input Stream Error" exception or "Unregistered class" exception. Here is what I do:

首先,我定义我的类:

#include <fstream>
#include <iomanip>

#include <boost/archive/xml_iarchive.hpp>
#include <boost/archive/xml_oarchive.hpp>
#include <boost/archive/archive_exception.hpp>
#include "boost/serialization/split_free.hpp"
#include "boost/serialization/export.hpp"
#include "boost/serialization/utility.hpp"
#include <boost/serialization/string.hpp>
#include <boost/serialization/binary_object.hpp>

class Base
{
public:
    bool isEnabled;
    Base();
    virtual ~Base(){}
};
Base::Base()
{
    isEnabled = 0;
}

class Derived : public Base
{

public:
    Derived();
    virtual ~Derived(){}
    int layerHeight;
};
Derived::Derived():Base()
{}

然后我要确保他们的特点是什么,我需要:

Then I make sure their traits are what I need:

BOOST_CLASS_EXPORT_GUID(Base, "Base")
BOOST_SERIALIZATION_SPLIT_FREE(Base)
BOOST_CLASS_IS_WRAPPER(Base)
BOOST_CLASS_TRACKING(Base, boost::serialization::track_selectively)
BOOST_CLASS_IMPLEMENTATION(Base, boost::serialization::object_class_info)

BOOST_SERIALIZATION_SPLIT_FREE(Derived)
BOOST_CLASS_EXPORT_GUID(Derived, "Derived")
BOOST_CLASS_IS_WRAPPER(Derived)
BOOST_CLASS_IMPLEMENTATION(Derived, boost::serialization::object_class_info)
BOOST_CLASS_TRACKING(Derived, boost::serialization::track_selectively)

接下来,我定义实际保存/加载功能:

Next I define actual save/load functions:

namespace boost {

    namespace serialization {

    template<class Archive>
    void save(Archive & ar,const Base& obj, const unsigned int version)
    {
        bool isEnabled = obj.isEnabled;
        ar << BOOST_SERIALIZATION_NVP(isEnabled);
    }
    template<class Archive>
    void load(Archive & ar, Base& obj, const unsigned int version)
    {
        bool isEnabled;
        ar >> BOOST_SERIALIZATION_NVP(isEnabled);
    }
    } // namespace serialization
} // namespace boost

namespace boost {
template<>
struct is_virtual_base_of<Base, Derived>: public mpl::true_ {};

namespace serialization {

template<class Archive>
void save(Archive & ar,const Derived& obj, const unsigned int version)
{
    ar & boost::serialization::base_object<Base>(obj);
    int height =obj.layerHeight;
    ar << BOOST_SERIALIZATION_NVP(height);
}
template<class Archive>
void load(Archive & ar, Derived& obj, const unsigned int version)
{
    ar.template register_type<Base>();
    ar.template register_type<Derived>();
    ar & boost::serialization::base_object<Base>(obj);
    int height;
    ar >> BOOST_SERIALIZATION_NVP(height);
}
} // namespace serialization
} // namespace boost

和2 SAVE / LOAD帮手,我从文档

And 2 save/load helpers I borrowed from Docs

template <typename T>
void save_schedule(const T& s, const char * filename){
    // make an archive
    std::ofstream ofs(filename);
    assert(ofs.good());
    boost::archive::xml_oarchive oa(ofs);
    oa << BOOST_SERIALIZATION_NVP(s);
}

template <typename T>
void restore_schedule(T &s, const char * filename)
{
    // open the archive
    std::ifstream ifs(filename);
    assert(ifs.good());
    boost::archive::xml_iarchive ia(ifs);
    // restore the schedule from the archive
    ia >> BOOST_SERIALIZATION_NVP(s);
}

最后 - 这里是我尝试使用它

Finally - here is how I try to use it all

int main(int argc, char *argv[])
{
    Base* basePointer = new Base();
    Base* objectPointer = new Derived();
    Derived * secondObjectPointer = new Derived();
    Derived justObject;

    save_schedule(basePointer, "C:\\basePointer.xml");
    save_schedule(objectPointer, "C:\\objectPointer.xml");
    save_schedule(secondObjectPointer , "C:\\secondObjectPointer.xml");
    save_schedule(justObject, "C:\\justObject.xml");

    //this works OK
    restore_schedule(basePointer, "C:\\basePointer.xml");

    //this gives "Input Stream Error"
    restore_schedule(objectPointer, "C:\\objectPointer.xml");

    //this gives "Unregistered class"
    restore_schedule(secondObjectPointer, "C:\\secondObjectPointer.xml");

    //This works >__< But I need to serialize pointers so I cannot use this
    restore_schedule(justObject, "C:\\justObject.xml");
}

我是什么做错了吗?为什么我不能反序列化不是一个指针其他任何一个基类?

What am I doing wrong? Why can't I deserialize anything other than a pointer to a base class?

推荐答案

UPD ::经过一番搜索,我能够追踪我的问题,以这样的回答:

<一个href=\"http://stackoverflow.com/questions/4432019/boost-serialization-exception-unregistered-class-serializing-polymorphic-base\">boost序列化异常:未注册类,序列多态基问题

替换

//original taken from Boost Docs
ar & boost::serialization::base_object<Base>(obj); 

// taken from the link above (macro expanded)
ar & boost::serialization::make_nvp( BOOST_PP_STRINGIZE(obj),boost::serialization::base_object<Base >(obj));

确实解决问题。

作为附带说明 - 我找到了另一种奇怪的错误中可能出​​现并导致流输入错误。它的工作原理是这样的:

As a side note - I've found another type of weird error that can arise and cause "stream input error". It works like this:

如果甚至有一个构造层次结构中,可以初始化变量(任何变量),但不 - 你会得到流输入错误尝试反序列化

If there is even ONE constructor in your hierarchy that CAN initialize a variable (any variable) but doesn't - you will get stream input error trying to deserialize.

如果有在的一类不变量 - 所有正常。但如果连一个 - 你必须在类的构造函数初始化至少一个变量!我不知道为什么这是重要的,但是这解决了一个大问题对我来说。

If there are no variables in a class - all is OK. But if there is even one - you MUST initialize at least one variable in the constructor of that class! I have no idea why is this important but this solved a major issue for me.

这篇关于使用Boost反序列化一个指向派生类的问题:序列化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆