クラスをシリアル化できるようにするには、主に 5 つの手順が必要です。 以下に一覧表示し、次のセクションで説明します。
CObject から ( または
CObject
から派生したクラスから) クラスを派生します。クラス宣言で DECLARE_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 メンバー関数をオーバーライドするには
基底クラスバージョンの
Serialize
を呼び出して、オブジェクトの継承された部分がシリアル化されていることを確認します。クラスに固有のメンバー変数を挿入または抽出します。
挿入および抽出演算子は、アーカイブ クラスと対話してデータの読み取りと書き込みを行います。 次の例は、上記で宣言した
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を使用できます。 使用法と例については、クラス CArchive
の GetObjectSchema
メンバー関数を参照してください。
次の例は、CObject
から派生したクラス (CPerson
) にIMPLEMENT_SERIALを使用する方法を示しています。
IMPLEMENT_SERIAL(CPerson, CObject, 1)
シリアル化可能なクラスを作成したら、「シリアル化: オブジェクトのシリアル化」の記事で説明されているように、クラスの オブジェクトをシリアル化できます。