4

boost::serializationを使用して変更できないカスタム クラスをシリアル化しようとしています。シリアル化部分からロジック/計算コードを分離する必要があります。シリアル化する必要がある保護されたプライベート フィールドがいくつかあり、それらのいくつかは他のクラスのboost::shared_ptrです。

何かのようなもの:

// computational classes
class A
{
public:
   A(int a) : m_val(a) {}
private:
   int m_val
};

class B
{
public:
   B(a) : m_ptr(new A(a)) {}
private:
   boost::shared_ptr< A > m_ptr;
};

クラスAをシリアル化するために私が見つけた簡単な回避策は、その定義に「フレンドクラス」を追加するだけです。

class A_ser;
class A
{
   friend class A_ser;
   //...
};

クラスAのフィールドへの参照を持つプロキシクラスを追加してシリアライズします。

class A_ser
{
public:
   A_ser(A & a) : m_val(A.m_val) {}
   template< class Archive >
   void serialize(Archive & ar, const unsigned int version)
   {
      ar & m_val;
   }
private:
   int & m_val;
};

namespace boost {
namespace serialization {
template< class Archive >
void serialize(Archive & ar, A & a, const unsigned int version)
{
   A_ser sa(a);
   ar & sa;
}
} // namespace serialization
} // namespace boost

そのため、シリアル化メソッドが A で呼び出されると、代わりに A_ser のメソッドが使用されます。

クラス B で同じことをしようとすると問題が発生します。その逆シリアル化では、定義されていないコンストラクター A() を呼び出そうとするためです。

boost/serialization/access.hpp:132: エラー: 'A::A()' の呼び出しに一致する関数がありません

A のコンストラクターにデフォルトの引数を入れようとすると、まったく新しい空のクラスが初期化されます。

ああ、ブースト 1.53.0 を使用しています。

よろしくお願いします。

編集:解決策(とても簡単でした..)

*_ser 参照を変更するだけで

class A_ser
{
public:
   A_ser(A & a) : m_a(A) {}
   template< class Archive >
   void serialize(Archive & ar, const unsigned int version)
   {
      ar & m_a.m_val;
   }
private:
   A & m_a;
};

と追加

template< class Archive >
void load_construct_data(Archive & /*ar*/, A * t, unsigned /*v*/)
{
   ::new(t) A(0);
}

問題は解決しました(Arunさんに感謝)!!

4

1 に答える 1

2

デフォルトで構築できないオブジェクトをブーストアプローチでシリアライズすることで問題を解決できます。save_construct_data と load_construct_data の使用例については、Google で調べてください。

Splitting serialize into Save/Loadもご覧ください。

于 2013-04-08T02:27:04.603 に答える