次の方法で共有


シリアル化: シリアル化可能なクラスの作成

クラスをシリアル化できるようにするには、主に 5 つの手順が必要です。 以下に一覧表示し、次のセクションで説明します。

  1. CObject から ( または CObject から派生したクラスから) クラスを派生します。

  2. Serialize メンバー関数のオーバーライド

  3. クラス宣言で DECLARE_SERIAL マクロを使用する。

  4. 引数を受け取たないコンストラクターを定義する

  5. クラスの実装ファイルで IMPLEMENT_SERIAL マクロを使用する。

CArchive の>>演算子と<<演算子ではなく、Serializeを直接呼び出す場合、最後の 3 つの手順はシリアル化に必要ありません。

CObject からクラスを派生する

基本的なシリアル化プロトコルと機能は、 CObject クラスで定義されています。 クラスCPersonの次の宣言に示すように、クラスをCObject (または CObject から派生したクラスから) 派生させることで、CObjectのシリアル化プロトコルと機能にアクセスできます。

シリアル化メンバー関数のオーバーライド

CObject クラスで定義されている Serialize メンバー関数は、オブジェクトの現在の状態をキャプチャするために必要なデータを実際にシリアル化します。 Serialize関数には、オブジェクト データの読み取りと書き込みに使用するCArchive引数があります。 CArchive オブジェクトには、IsStoringメンバー関数があります。これは、Serializeがデータの格納 (データの書き込み) か読み込み (データの読み取り) かを示します。 IsStoringの結果をガイドとして使用して、挿入演算子 (<<) を使用してオブジェクトのデータをCArchive オブジェクトに挿入するか、抽出演算子 (>>) を使用してデータを抽出します。

CObjectから派生し、CString型と WORD 型の 2 つの新しいメンバー変数を持つクラスについて考えてみましょう。 次のクラス宣言フラグメントは、新しいメンバー変数と、オーバーライドされた Serialize メンバー関数の宣言を示しています。

class CPerson : public CObject
{
public:
   DECLARE_SERIAL(CPerson)
   // empty constructor is necessary
   CPerson();
   virtual ~CPerson();

   CString m_name;
   WORD   m_number;

   void Serialize(CArchive& archive);
};

Serialize メンバー関数をオーバーライドするには

  1. 基底クラスバージョンの Serialize を呼び出して、オブジェクトの継承された部分がシリアル化されていることを確認します。

  2. クラスに固有のメンバー変数を挿入または抽出します。

    挿入および抽出演算子は、アーカイブ クラスと対話してデータの読み取りと書き込みを行います。 次の例は、上記で宣言したCPerson クラスのSerializeを実装する方法を示しています。

    void CPerson::Serialize(CArchive& archive)
    {
       // call base class function first
       // base class is CObject in this case
       CObject::Serialize(archive);
    
       // now do the stuff for our specific class
       if (archive.IsStoring())
          archive << m_name << m_number;
       else
          archive >> m_name >> m_number;
    }
    

また、CArchive::Read および CArchive::Write メンバー関数を使用して、大量の型指定されていないデータを読み書きすることもできます。

DECLARE_SERIAL マクロの使用

次に示すように、シリアル化をサポートするクラスの宣言では、DECLARE_SERIAL マクロが必要です。

class CPerson : public CObject
{
public:
   DECLARE_SERIAL(CPerson)

引数のないコンストラクターの定義

MFC では、オブジェクトが逆シリアル化 (ディスクから読み込まれる) ときにオブジェクトを再作成するときに、既定のコンストラクターが必要です。 逆シリアル化プロセスでは、すべてのメンバー変数に、オブジェクトの再作成に必要な値が入力されます。

このコンストラクターは、パブリック、保護、またはプライベートとして宣言できます。 保護またはプライベートにする場合は、シリアル化関数でのみ使用されるようにしてください。 コンストラクターは、必要に応じてオブジェクトを削除できる状態にする必要があります。

DECLARE_SERIALマクロとIMPLEMENT_SERIALマクロを使用するクラスで引数のないコンストラクターを定義することを忘れた場合は、IMPLEMENT_SERIAL マクロが使用されている行に "既定のコンストラクターが使用できません" というコンパイラ警告が表示されます。

実装ファイルでの IMPLEMENT_SERIAL マクロの使用

IMPLEMENT_SERIAL マクロは、 CObjectからシリアル化可能なクラスを派生するときに必要なさまざまな関数を定義するために使用されます。 このマクロは、実装ファイル (.CPP) を使用します。 マクロの最初の 2 つの引数は、クラスの名前と、その即時基底クラスの名前です。

このマクロの 3 番目の引数はスキーマ番号です。 スキーマ番号は、基本的にクラスのオブジェクトのバージョン番号です。 スキーマ番号には、0 以上の整数を使用します。 (このスキーマ番号とデータベースの用語を混同しないでください)。

MFC シリアル化コードは、オブジェクトをメモリに読み込むときにスキーマ番号をチェックします。 ディスク上のオブジェクトのスキーマ番号がメモリ内のクラスのスキーマ番号と一致しない場合、ライブラリは CArchiveExceptionをスローし、プログラムが正しくないバージョンのオブジェクトを読み取らないようにします。

Serializeメンバー関数が複数のバージョン (つまり、アプリケーションの異なるバージョンで書き込まれたファイル) を読み取ることができるようにする場合は、IMPLEMENT_SERIAL マクロの引数として値VERSIONABLE_SCHEMAを使用できます。 使用法と例については、クラス CArchiveGetObjectSchema メンバー関数を参照してください。

次の例は、CObjectから派生したクラス (CPerson) にIMPLEMENT_SERIALを使用する方法を示しています。

IMPLEMENT_SERIAL(CPerson, CObject, 1)

シリアル化可能なクラスを作成したら、「シリアル化: オブジェクトのシリアル化」の記事で説明されているように、クラスの オブジェクトをシリアル化できます。

こちらも参照ください

シリアル化