シリアル化 : シリアル化可能なクラスの作成
クラスをシリアル化できるようにするには、5 つの主要な手順を実行する必要があります。 これらは次のセクションで説明されています。
CObject から (または
CObject
から派生するクラスから) クラスを派生します。クラス宣言で、DECLARE_SERIAL macro マクロを使用します。
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
の基底クラスのバージョンを呼び出して、継承されたオブジェクト部分がシリアル化されるようにします。クラスに固有のメンバー変数を挿入または抽出します。
挿入演算子と抽出演算子は アーカイブ クラスとやり取りして、データの読み取りと書き込みを行います。 次の例は、上記で宣言した
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 では、オブジェクトが逆シリアル化される (ディスクから読み込まれる) ときに、既定のコンストラクターが必要になります。 逆シリアル化プロセスでは、オブジェクトを再作成するために必要な値がすべてのメンバー変数に入力されます。
このコンストラクターは、public、protected、または private として宣言できます。 保護またはプライベートにすると、シリアル化関数によってのみ使用されるようになります。 コンストラクターは、必要に応じてオブジェクトを削除できる状態にする必要があります。
Note
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)
シリアル化可能なクラスを作成した後は、「シリアル化: オブジェクトのシリアル化」で説明されているように、クラスのオブジェクトをシリアル化できます。