使用 boost 序列化抽象类时出错

2024-03-09

我正在尝试序列化我的数据结构,以便将它们写入 TCP 套接字。

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

BOOST_SERIALIZATION_ASSUME_ABSTRACT(T)

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

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

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

我的数据结构比这个复杂一点,但我们假设我有以下结构

坐标.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;
    }
};

移动法线.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);
    }
};

虚拟方法在这里定义。

移动法线.cpp

#include "MoveNormal.h"

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

我的 main.cpp 如下所示:

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

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

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

我正在使用 VS2010 和 Boost 1.48.0。


这有点奇怪,但我要回答我自己的问题。我刚刚弄清楚如何使上面的示例发挥作用。

这就是解决方案。每次我们需要序列化一个从另一个类继承属性的类时,我们都需要使用宏:

BOOST_CLASS_EXPORT(T)

根据boost序列化文档 http://www.boost.org/doc/libs/1_48_0/libs/serialization/doc/special.html#export

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

请注意,此功能的实现要求 BOOST_CLASS EXPORT 宏出现在要实例化代码的任何存档类标头之后并包含其中。

所以就我而言,我的 main.cpp 文件现在是:

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

只需确保在使用导出宏之前包含所需的所有升压档案即可。

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

所以我们假设我有一个像这样的连接标头this one http://www.boost.org/doc/libs/1_48_0/doc/html/boost_asio/example/serialization/connection.hpp现在我在 MoveJump.h 中定义了另一个名为 MoveJump 的类

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

现在序列化这些结构我的主要看起来像这样

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

诀窍是注册当我们有指向基类的指针时将被序列化的类。

如果在我的 Move.h 中我有更多指向其他基类的指针(我在项目中这样做),我们需要在 main 中包含所有标头并注册扩展基类的所有可能的类。

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

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

Thanks

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 boost 序列化抽象类时出错 的相关文章

随机推荐