5

データ構造をtcpソケットに書き込むために、データ構造をシリアル化しようとしています。

これまでのところ、私の問題はシリアル化であることがわかりました。私も使ってみました

BOOST_SERIALIZATION_ASSUME_ABSTRACT(T)

しかし、私のプログラムとそれを正しく実装する方法に似た実用的な例を見つけることができません。

これが私が訪れたリンクのいくつかです:

私のデータ構造はこれより少し複雑ですが、私が次の構造を持っていると仮定しましょう

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

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

#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とBoost1.48.0を使用しています。

4

2 に答える 2

7

これは少し奇妙ですが、私は自分の質問に答えるつもりです。上記の例を機能させる方法を理解しました。

ここに解決策があります。別のクラスから属性を継承するクラスをシリアル化する必要があるたびに、マクロを使用する必要があります。

BOOST_CLASS_EXPORT(T)

ブーストシリアル化ドキュメントによると

アーカイブクラスヘッダーのいずれかを含む同じソースモジュール内の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ソケットに書き込む必要があります。

したがって、このような接続ヘッダーがあり、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内に、プロジェクトで行う他の基本クラスへのポインターがさらにある場合は、メインにすべてのヘッダーを含め、基本クラスを拡張するすべての可能なクラスを登録する必要があります。

これが将来同様の問題を抱えているかもしれない誰かに役立つことを願っています。

新しい可能な解決策を自由に提示してください。

ありがとう

于 2011-12-04T15:13:56.003 に答える
0

大まかに言えば、単純に BOOST_CLASS_EXPORT を使ってすべてのクラスを登録するか、スーパークラスに BOOST_SERIALIZATION_ASSUME_ABSTRACT を使用し、「archive」のメンバー関数 register_type を併用することができます。参照: Boost.serialize を使用して派生テンプレート クラスをシリアル化する方法 詳細については(私の下手な英語で申し訳ありません:))

于 2013-11-26T14:44:22.457 に答える