升压反序列化派生类的基类指针 [英] Boost deserialize a derived class to base class pointer

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

问题描述

请帮我反序列化派生类的基类指针。我附上完整的源代码code的例子。

Please help me deserialize a derived class to base-class pointer. I attach the complete source code example.

request.hpp (没有对CPP文件)

request.hpp (no pair cpp file)

#ifndef REQUEST_HPP
#define REQUEST_HPP

#include <memory>
#include <string>

#include <boost/archive/xml_oarchive.hpp>
#include <boost/archive/xml_iarchive.hpp>

namespace demo {
namespace common {

        class request {
        public:
            static const int INVALID_ID = -42;

            request() 
                : id_(INVALID_ID), timestamp_(0), source_ip_("unknown") {};

            request(int id, long timestamp, const std::string& source_ip) 
                : id_(id), timestamp_(timestamp), source_ip_(source_ip) {};

            virtual ~request() {};

            int id() const { return id_; }
            long timestamp() const { return timestamp_; }
            std::string source_ip() const { return source_ip_; }



        protected:
            int id_;
            long timestamp_;
            std::string source_ip_;



        private:
            friend class boost::serialization::access;

            template<class Archive>
            void serialize(Archive& ar, const unsigned version) {
                ar & BOOST_SERIALIZATION_NVP(id_);
                ar & BOOST_SERIALIZATION_NVP(timestamp_);
                ar & BOOST_SERIALIZATION_NVP(source_ip_);
            }

        };

        typedef std::shared_ptr<request> request_ptr;

    }
};

#endif

command.hpp (派生类)

#ifndef COMMAND_HPP
#define COMMAND_HPP

#include <memory>
#include <string>

#include <boost/serialization/export.hpp>

#include <demo/common/request.hpp>

namespace demo {
    namespace common {

            class command : public request {
            public:
                command(): name_("untitled") {};
                explicit command(const std::string& name) : name_(name) {};
                virtual ~command() {};

                virtual void execute();

                std::string name() const { return name_; }

            protected:
                std::string name_;

            private:
                friend class boost::serialization::access;

                template<class Archive>
                void serialize(Archive& ar, const unsigned version) {
                    ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(request);
                    ar & BOOST_SERIALIZATION_NVP(name_);
                }

            };

            typedef std::shared_ptr<command> command_ptr;

        }
};

BOOST_CLASS_EXPORT_KEY(demo::common::command)


#endif

command.cpp

#include "command.hpp"
#include <iostream>

BOOST_CLASS_EXPORT_IMPLEMENT(demo::common::command)

namespace demo {
    namespace common {

            void command::execute() {
                std::cout << "  I am '" + name_ +"' and I am executing..." << std::endl;
            }

    }
};

serializer.hpp

#ifndef SERIALIZER_HPP
#define SERIALIZER_HPP

#include <sstream>
#include <string>

/* classes to serialize */
#include <demo/common/request.hpp>
#include <demo/common/command.hpp>

namespace demo {
    namespace common {

        class serializer {
        public:
            serializer() : {};

            template<typename T>
            std::string serialize(const T& t){  
                std::stringstream stream;
                boost::archive::xml_oarchive archive(stream);
                archive << BOOST_SERIALIZATION_NVP(t);
                std::string serialized = stream.str();

                return serialized;
            }


            template<typename T>
            void deserialize(const std::string& serialized, T& t) {
                std::stringstream stream(serialized);
                boost::archive::xml_iarchive archive(stream);
                archive >> BOOST_SERIALIZATION_NVP(t);
            }
        };

    }
}

#endif

示例用法

#include <iostream>

#include <demo/common/serializer.hpp>
#include <demo/common/command.hpp>


using namespace std;
using namespace demo::common;

int main(){
    serializer serializer_;

    command r("123"); // <-- (1) my desired way of declaring
    //request* r = new command("123"); <-- (2) replacing with this makes all work!
    //command* r = new command("123"); <-- (3) replacing with this crashes the app, like (1)
    std::string s = serializer_.serialize(r);
    std::cout << s << std::endl;
    request* rr = nullptr;
    serializer_.deserialize(s, rr); //this throws an exception

    command* rrr = dynamic_cast<command*>(rr);

    rrr->execute();
}

我想我这样做需要做的一切,包括档案的任何类出口之前,所有的默认构造初始化成员。

I thought I did everything that needs to be done, archives included before any class export, all default constructors initialize members..

请注意,序列化类和串行被编译为一个库文件。然后该库在可以访问的标题和具有lib中连接的两个子项目中使用。他们使用这些类相互通信时,它们通过网络发送序列化对象。

Note that the serializable classes and the serializer are compiled to a lib file. Then that lib is used in two sub-projects that have access to the headers and have that lib linked. They use those classes to communicate with each other, they send serialized objects over network.

我为什么不能反序列化派生类的基类指针?
我使用Boost 1.51和VC11。

Why can't I deserialize a derived class to a base class pointer? I am using Boost 1.51 and VC11.

推荐答案

您可能正在使用您的库时得到一个的 input_stream_error 的在您的演示和 unregistered_class 的异常。这是由升压方式造成正在注册的类,在你的情况下,自动完成。

You're probably getting an input_stream_error in your demo and unregistered_class exception when using your library. This is caused by the way boost is registering the classes, in your case, automatically.

看来,自动注册过程会很困惑,当你序列化派生类对象和反序列化到它的基地,尽管使用了BOOST_CLASS_EXPORT *宏。

It appears that the automatic registration process gets confused when you serialize a derived object and deserialize to its base, despite the use of the BOOST_CLASS_EXPORT* macros.

不过,可以明确的注册类您在存档执行任何I / O操作前:

However, you can register the classes explicitly before you perform any i/o operation on the archive:

// ...
boost::archive::xml_iarchive archive(stream);
// register the class(es) with the archive
archive.template register_type<command>();
archive >> BOOST_SERIALIZATION_NVP(t);
// ...

序列化时使用登记顺序相同。这使得出口宏多余的。

Use the same order of registration when serializing. This makes the export macros superfluous.

这篇关于升压反序列化派生类的基类指针的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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