使用Boost序列化抽象类时出错 [英] Error serializing an abstract class with boost

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

问题描述

我正在尝试序列化我的数据结构以便将其写入tcp套接字。

I'm trying to serialize my data structures in order to write them to a tcp socket.

到目前为止,我发现我的问题是序列化。我什至尝试使用

So far I found that my problem is the serialization. I even tried to use

BOOST_SERIALIZATION_ASSUME_ABSTRACT(T)

,但是我找不到任何类似于我的程序以及如何正确实现该示例的工作示例。

but I can't find any working example similar to my program and how to implement it correctly.

以下是我访问过的一些链接:

Here are some of the links that I have visited:

  • http://programmers-blog.com/category/c-c
  • http://www.boost.org/doc/libs/1_48_0/libs/serialization/doc/tutorial.html#simplecase
  • http://en.highscore.de/cpp/boost/serialization.html#serialization_class_hierarchies

我的数据结构稍微复杂一点如果是这样,那么我们假设我具有以下结构

My data structures are a little more complicated then this one but let's assume that I have the following structure

Coordinate.h

Coordinate.h

#include <boost\archive\text_iarchive.hpp>
#include <boost\archive\text_oarchive.hpp>

class Coordinate {
public:
    Coordinate() {}
    Coordinate(int c) : c(c) {}
    int get(void) { return c; }
    std::string toString(void);
private:
    int c;
    friend class boost::serialization::access;
    template<typename Archive>
    void serialize(Archive &ar, const unsigned int version) {
        ar & this->c;
    }
};

Move.h

class Coordinate;

#include "Coordinate.h"

#include <boost\archive\text_iarchive.hpp>
#include <boost\archive\text_oarchive.hpp>

class Move {
public:
    Move() {}
    ~Move() {}
    Coordinate* getCoordinate(void) {return this->destination; }
    virtual bool isJump(void) = 0;
protected:
    Coordinate *destination;
private:
    friend class boost::serialization::access;
    template<typename Archive>
    void serialize(Archive &ar, const unsigned int version) {
        ar & this->destination;
    }
};

MoveNormal.h

MoveNormal.h

class Coordinate;

#include "Move.h"
#include "Coordinate.h"

#include <boost\archive\text_iarchive.hpp>
#include <boost\archive\text_oarchive.hpp>

class MoveNormal : public Move {
public:
    MoveNormal() {}
    MoveNormal(Coordinate *destination) { this->destination = destination; }
    ~MoveNormal() {}
    virtual bool isJump(void);
private:
    friend class boost::serialization::access;
    template<typename Archive>
    void serialize(Archive &ar, const unsigned int version) {
        ar & boost::serialization::base_object<Move>(*this);
    }
};

此处定义了虚拟方法。

MoveNormal.cpp

MoveNormal.cpp

#include "MoveNormal.h"

bool MoveNormal::isJump(void) {
    return false;
}

我的main.cpp看起来像这样:

My main.cpp looks like this:

#include "Coordinate.h"
#include "Move.h"
#include "MoveNormal.h"

#include <fstream>

#include <boost\archive\text_iarchive.hpp>
#include <boost\archive\text_oarchive.hpp>

int main(int argc, char *argv[]) {
    Coordinate *c = new Coordinate(10);
    // This runs OK
    /*
    {
        std::ofstream ofs("f.txt");
        boost::archive::text_oarchive oa(ofs);
        oa << c;
    }
    Coordinate *d;
    {
        std::ifstream ifs("f.txt");
        boost::archive::text_iarchive ia(ifs);
        ia >> d;
    }
    std::cout << "c.get(): " << c->get() << std::endl;
    std::cout << "d.get(): " << d->get() << std::endl;
    */

    // This is where I get my error
    Move *m  = new MoveNormal(c);
    {
        std::ofstream ofs("f.txt");
        boost::archive::text_oarchive oa(ofs);
        oa << m;    // Line where the error occurs
    }
    return 0;
}

但是当我运行程序时,出现以下错误:

But when I run the program I get the following error:


Test.exe中0x76dbb9bc处未处理的异常:Microsoft C ++异常:内存位置0x001df078处的boost :: archive :: archive_exception ..

Unhandled exception at 0x76dbb9bc in Test.exe: Microsoft C++ exception: boost::archive::archive_exception at memory location 0x001df078..

我正在使用VS2010和Boost 1.48.0。

I'm using VS2010, and Boost 1.48.0.

推荐答案

这有点奇怪,但是我要回答我自己的问题。我只是想出了使上面的示例工作的方法。

This is a little bit weird but I'm going to answer my own question. I just figured out how to make my example above work.

在这里可以解决问题。每次我们需要序列化一个从另一个类继承属性的类时,我们都需要使用宏:

Here it goes the solution. Everytime we need to serialize a class that inherits attributes from another class we need to use the macro:

BOOST_CLASS_EXPORT(T)

根据提升序列化文档


BOOST_CLASS_EXPORT在同一源模块中包括任何存档类标头将实例化将指示类型的多态指针序列化到所有那些存档类所需的代码。如果不包含任何存档类头文件,则不会实例化代码。

BOOST_CLASS_EXPORT in the same source module that includes any of the archive class headers will instantiate code required to serialize polymorphic pointers of the indicated type to the all those archive classes. If no archive class headers are included, then no code will be instantiated.

请注意,此功能的实现要求BOOST_CLASS_EXPORT宏出现在所有存档之后,并包含所有存档

Note that the implemenation of this functionality requires that the BOOST_CLASS_EXPORT macro appear after and the inclusion of any archive class headers for which code is to be instantiated.

所以在我的情况下,我的main.cpp文件现在是:

So in my case my main.cpp file is now:

#include <fstream>

#include <boost\archive\text_iarchive.hpp>
#include <boost\archive\text_oarchive.hpp>
#include <boost\serialization\export.hpp>

#include "Coordinate.h"
#include "Move.h"
#include "MoveNormal.h"
BOOST_CLASS_EXPORT(MoveNormal)

int main(int argc, char *argv[]) {
    Coordinate *c = new Coordinate(150);
    Move *m = new MoveNormal(c);
    std::cout << "m.getDestination().get(): " << m->getDestination()->get() << std::endl;
    {
        std::ofstream ofs("f.txt");
        boost::archive::text_oarchive oa(ofs);
        oa << m;
    }

    Move *n;
    {
        std::ifstream ifs("f.txt");
        boost::archive::text_iarchive ia(ifs);
        ia >> n;
    }
    std::cout << "n.getDestination().get(): " << n->getDestination()->get() << std::endl;
    return 0;
}

在使用前,请确保已包含所需的所有增强存档。

Just make sure that you include all the boost archives you need before you use the export MACRO.

除了序列化之外,要完成我的项目,我需要使用boost :: asio将它们写入tcp套接字。

To finish my project besides the serialization I need to write them to a tcp socket using boost::asio.

因此,假设我有一个连接标头,例如这个,现在我在MoveJump.h中定义了另一个名为MoveJump的类。

So let's assume that I have a connection header like this one and that now I have another class called MoveJump defined in my MoveJump.h

#include <boost\archive\text_iarchive.hpp>
#include <boost\archive\text_oarchive.hpp>

#include "Coordinate.h"
#include "Move.h"

class MoveJump : public Move {
public:
    MoveJump() {}
    MoveJump(Coordinate *c) { this->destinatio = c; }
    ~MoveJump() {}
    virtual bool isJump(void);
private:
    friend class boost::serialization::access;
    template<typename Archive>
    void serializize(Archive &ar, const unsigned int version) {
        ar & boost::serialization::base_object<Move>(*this);
    }
};

现在要序列化这些结构,我的主要外观是这样

Now to serialize these structures my main look like this

#include <boost\archive\text_iarchive.hpp>
#include <boost\archive\text_oarchive.hpp>
#include <boost\serialization\export.hpp>

#include <fstream>

#include "Coordinate.h"
#include "Move.h"
// And now we register all the possible Moves
#include "MoveNormal.h"
BOOST_CLASS_EXPORT(MoveNormal)
#include "MoveJump.h"
BOOST_CLASS_EXPORT(MoveJump)

int main(int argc, char *argv[]) {
    Coordinate *c = new Coordinate(10);
    Move *m = new MoveNormal(c);
    Coordinate *d = new Coordinate(15);
    Move *j = new MoveJump(d);
    {
        std::ofstream ofs("m.txt");
        boost::archive::text_oarchive oa(ofs);
        oa << m;
    }
    {
        std::ofstream ofs("j.txt");
        boost::archive::text_oarchive oa(ofs);
        oa << j;
    }
}

技巧是注册将要序列化的类当我们有指向基类的指针时。

The trick is to register the classes that will be serialized when we have the pointer to the base class.

如果在我的Move.h中,我有更多指向其他基类的指针,这在我的项目中也需要进行。

If inside my Move.h I have more pointers to other base classes, which I do in my project, we need to include in the main all the headers and register all the possible classes that expand the base class.

我希望这对将来可能会遇到类似问题的人有所帮助。

I hope this helps someone who might have similar problems in the future.

p>

随时提出新的可能解决方案。

Feel free to present new possible solutions.

谢谢

这篇关于使用Boost序列化抽象类时出错的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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