2

私には3つのクラスがあります:

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

    template<class Archive>
    void serialize(Archive & ar, const unsigned int version)
    {
        ar & this->id & this->somefield;
    }
protected:
    A() {} // just for boost, normally I create this class with non-default constructor
    int id;
    Sometype somefield;
public:
    A(unsigned int id);
    // blah blah, also some virtual methods
};

// _____________________ CLASS B

class B : public A
{
private:
    friend class boost::serialization::access;

    template<class Archive> inline friend void load_construct_data(Archive &ar, B *t, const unsigned int file_version);
    template<class Archive> inline friend void save_construct_data(Archive &ar, const B *t, const unsigned int file_version);

    B(unsigned int id, Sometype somefield, Sometype some_new_field1, Sometype some_new_field2);

    Sometype some_new_field1;
    Sometype some_new_field2;

    template<class Archive>
    void serialize(Archive & ar, const unsigned int version) {
        ar & boost::serialization::base_object<A>(*this);
    }


public:
    // blah blah, also virtual methods
};

template<class Archive>
inline void save_construct_data(
    Archive & ar, const B * t, const unsigned int file_version
){
    ar << t->id << t->somefield << t->some_new_field1 << t->some_new_field2;
}

template<class Archive>
inline void load_construct_data(
    Archive & ar, B * t, const unsigned int file_version
){
    unsigned int _id;
    Sometype _somefield;

    Sometype _some_new_field1;
    Sometype _some_new_field2;


    ar >> _id >> _somefield >> _some_new_field1 >> _some_new_field2;

    ::new(t)B(_id, _somefield, _some_new_field1, _some_new_field2);
}

// _____________________ CLASS C

class C : public A
{
private:
    friend class boost::serialization::access;

    template<class Archive> inline friend void load_construct_data(Archive &ar, C *t, const unsigned int file_version);
    template<class Archive> inline friend void save_construct_data(Archive &ar, const C *t, const unsigned int file_version);

    C(unsigned int id, Sometype somefield, Sometype some_new_field3, Sometype some_new_field4);

    Sometype some_new_field3;
    Sometype some_new_field4;

    template<class Archive>
    void serialize(Archive & ar, const unsigned int version) {
        ar & boost::serialization::base_object<A>(*this);
    }


public:
    // blah blah, also virtual methods
};

template<class Archive>
inline void save_construct_data(
    Archive & ar, const C * t, const unsigned int file_version
){
    ar << t->id << t->somefield << t->some_new_field3 << t->some_new_field4;
}

template<class Archive>
inline void load_construct_data(
    Archive & ar, C * t, const unsigned int file_version
){
    unsigned int _id;
    Sometype _somefield;

    Sometype _some_new_field3;
    Sometype _some_new_field4;


    ar >> _id >> _somefield >> _some_new_field3 >> _some_new_field4;

    ::new(t)C(_id, _somefield, _some_new_field3, _some_new_field4);
}

デフォルト以外のコンストラクターを使用する必要があるため、load/save_construct_dataオーバーライドが必要です。クラスBとCは、ベクトルを介してシリアル化および逆シリアル化されるため、マクロBOOST_CLASS_EXPORT()を使用します(コードの別の部分では、無関係だと思います)。私の問題は、上記のコードで作成されたアーカイブを逆シリアル化すると、ベクター内に重複するポインターが取得されることです(それぞれがメモリ内の同じ領域を指します)-ベース用と派生クラス用のポインターである可能性があります。複製を作成せずに基本クラスへのポインターを介してオブジェクトを保存するときに、load/save_constructデータの使用方法をどこにも見つけることができません。私はこれに何週間も費やしました、そして私の締め切りは非常に速く近づいています、どんな助けも大いに感謝します:)

編集:もう1つ言及する必要があります:「serialize」メソッドのコンテンツを基本クラスから削除すると(メソッド自体ではなくコンテンツのみ)、逆シリアル化した後は何も取得せず、「base_object」を含むパーツを削除すると、アーカイブは例外「未登録のボイドキャスト」。

4

1 に答える 1

7

Boostマニュアルはあまりよくできていません、「テンプレートのシリアル化」セクションで私の答えを見つけました:)

基本クラスのシリアル化メソッドを空白のままにする必要があり、派生クラスではシリアル化メソッドを配置します

boost::serialization::void_cast_register<derived, base>();

将来の参考のために-今ではすべてが正常に動作します:)

于 2013-01-04T14:05:06.547 に答える