serialization - traits

シリアライズするクラスの特性の指定ができる。
よく使いそうなのを列挙すると
  • 抽象クラスか
  • ベースクラスのポインタを使ってシリアライズ可能にするか
  • オブジェクト追跡を行うか
  • クラスのバージョン番号
ぐらいかな。それぞれ見ていく。

抽象クラス
抽象クラスの場合、コンパイルエラーになることがある。
MFCでも IMPLEMENT_SERIAL マクロが抽象クラスに使えなくて、 抽象クラスには専用のマクロを使う必要があったりしたが、boostでも 同様に BOOST_IS_ABSTRACTマクロを使う必要がある。

BOOST_IS_ABSTRACT(MyClass); // MyClass は抽象クラス


ベースクラスのポインタを使ってシリアライズ可能
以前に、ベースクラスのポインタを使って派生クラスのシリアライズを可能にするために、シリアライズ前に register_type()を呼び出してクラスを登録しておく必要があると書いたが、あれは結構面倒。
かわりにBOOST_CLASS_EXPORT_GUIDマクロを使って特性を指定することでそれを省くことができ、とっても便利だ。

BOOST_CLASS_EXPORT_GUID(MyClass, "ユニークな文字列");
BOOST_CLASS_EXPORTマクロを使うとユニークな文字列をクラス名にしてくれる。
BOOST_CLASS_EXPORT(MyClass); // BOOST_CLASS_EXPORT_GUID(MyClass, "MyClass"); と同値


オブジェクト追跡
あるオブジェクトが2つのオブジェクトからポインタで関連付けられたりしている場合に、2重にシリアライズされてしまうのを防ぐために MFCでは ハッシュマップに シリアライズ済みのオブジェクトのポインタを登録しておき、すでにシリアライズ済みのオブジェクトだったらかわりにそれをあらわすIDを書き出すという処理を行っていた。
また、循環参照の場合にもこの処理を行わないと無限ループに陥ってしまう。
boostでも同様の処理を行っていて、これをオブジェクト追跡と呼んでいるみたいで、この動作を指定できる。
3つのモードがあって、

  • track_never = 常にOFF(組み込み型のデフォルト設定)
  • track_selectively = ポインタを介してシリアライズするときのみON。(その他のクラスのデフォルト設定)
  • track_always = 常にON
通常はデフォルトのままで問題がないが、ダイアモンド継承のときには常にONにする必要があるようだ。(でないと基底クラスが2重にシリアライズされる)。その場合BOOST_CLASS_TRACKINGマクロを使って次のように指定する。
BOOST_CLASS_TRACKING(MyClass, boost::serialization::track_always);


バージョン管理
クラスのメンバが変更したときなどのために、シリアライズ時にはクラスのバージョン番号が書き込まれ、serialize()メンバ関数の第2引数にその番号が渡されてくる。
この番号をみて処理を振り分けることで異なるバージョン間での互換性を保つことができる。
バージョン番号は BOOST_CLASS_VERSIONマクロで次のように指定する。

BOOST_CLASS_VERSION(MyClass, 3); // version = 3

指定しなかった場合のデフォルトのバージョン番号は 0。

<< serialization - XML archive Site Top serialization - デフォルトコンストラクタのないクラス >>

Comments