ま、そんなところで。

ニッチな技術系メモとか、車輪を再発明してみたりとか.

C++でMessagePackを使ってみる(2)〜 派生クラスの場合 〜

継承クラスを含めてシリアライズ/デシリアライズする

継承クラスの場合は基底クラスのメンバ変数もシリアライズ/デシリアライズしなければならないため、すこし手を加える必要があります.

クラスの定義

基本的な条件に加えて、 以下の条件を満たすように定義します.

  • MSGPACK_BASEで対象とする親クラスを指定
  • MSGPACK_BASEで指定されたクラスもMSGPACK_DEFINEをもつクラスであること.1
#include <iostream>
#include <string>

// 基底クラス
class Hoge {
public:
    // デシリアライズ用にデフォルトコンストラクタを用意しておく
    Hoge()
    : hoge_(0)
    , fuga_("HogeFuga")
    { }

    // パラメータ設定付きコンストラクタ
    Hoge(int hoge, std::string fuga)
    : hoge_(hoge)
    , fuga_(std::move(fuga))
    { }

    // シリアライズ設定. 対象とするメンバ変数を指定する.
    MSGPACK_DEFINE(hoge_, fuga_);
private:
    int hoge_;
    std::string fuga_;
};

// 派生クラス
class Derived : public Hoge {
private:
    using base_t = Hoge;
public:
    // デシリアライズ用のデフォルトコンストラクタ
    Derived()
    : base_t()
    , derived_member_(0)
    { }

    // パラメータ設定付きコンストラクタ
    Derived(int hoge, std::string fuga, size_t num)
    : base_t(hoge, std::move(fuga))
    , derived_member_(num)
    { }

    // シリアライズ設定. 基底クラスと 対象とするメンバ変数を指定する.
    MSGPACK_DEFINE( MSGPACK_BASE(base_t), derived_member_);
private:
    size_t derived_member_;
};

シリアライズ/デシリアライズ

定義さえ出来てしまえば、あとは普通にpackしてやればOK.

Derived derived(3, "abc", 6);
// シリアライズデータ用のバッファ
msgpack::sbuffer buffer;
// シリアライズ
msgpack::pack(buffer, derived);
// シリアライズデータ
char* pdata   = buffer.data();
size_t data_size   = buffer.size();
    :
// シリアライズデータを読み出す
msgpack::object_handle hd = msgpack::unpack(pdata, data_size);
const msgpack::object& obj = hd.get();
// デシリアライズ
Derived restored;
obj.convert(restored);

簡単〜♪


参考記事


  1. 厳密には「MessagePackでシリアライズ可能なクラス」だが、この件は別記事のほうに