アーカイブを通じた CObject の格納と読み込み
更新 : 2007 年 11 月
アーカイブを通じて CObject の格納と読み込みを行うときは注意が必要です。場合によっては、CArchive クラスの演算子 << または >> ではなく、オブジェクトの Serialize 関数を呼び出す必要があります。この場合は、CArchive オブジェクトが Serialize 関数呼び出しのパラメータになります。重要な違いは、CArchive クラスの >> 演算子は、格納用アーカイブによってファイルにあらかじめ書き込まれている CRuntimeClass 情報に基づき、CObject オブジェクトをメモリに動的に生成するという点です。
したがって、CArchive の演算子 << および >> を使用するか、Serialize 関数を呼び出すかどうかは、あらかじめ格納されている CRuntimeClass 情報に基づいて、読み込みアーカイブがオブジェクトを動的に再生成する必要があるかどうかによって判断します。次の場合は Serialize 関数を使います。
オブジェクトを逆シリアル化するとき、オブジェクトのクラスがわかっている場合
オブジェクトを逆シリアル化するとき、オブジェクトに対するメモリが既に確保されている場合
注意 : |
---|
Serialize関数を使ってオブジェクトを読み込んだ場合は、格納するときも Serialize 関数を使う必要があります。CArchive の << 演算子を使って格納したオブジェクトを Serialize 関数で読み込んだり、Serialize 関数を使って格納したオブジェクトを CArchive >> 演算子で読み込んだりしないでください。 |
そのような例を次に示します。
class CMyObject : public CObject
{
// ...Member functions
public:
CMyObject() { }
virtual void Serialize( CArchive& ar );
// Implementation
protected:
DECLARE_SERIAL( CMyObject )
};
class COtherObject : public CObject
{
// ...Member functions
public:
COtherObject() { }
virtual void Serialize( CArchive& ar );
// Implementation
protected:
DECLARE_SERIAL( COtherObject )
};
class CCompoundObject : public CObject
{
// ...Member functions
public:
CCompoundObject();
~CCompoundObject();
virtual void Serialize( CArchive& ar );
// Implementation
protected:
CMyObject m_myob; // Embedded object
COtherObject* m_pOther; // Object allocated in constructor
CObject* m_pObDyn; // Dynamically allocated object
//..Other member data and implementation
DECLARE_SERIAL( CCompoundObject )
};
IMPLEMENT_SERIAL(CMyObject,CObject,1)
IMPLEMENT_SERIAL(COtherObject,CObject,1)
IMPLEMENT_SERIAL(CCompoundObject,CObject,1)
CCompoundObject::CCompoundObject()
{
m_pOther = new COtherObject; // Exact type known and object already
//allocated.
m_pObDyn = NULL; // Will be allocated in another member function
// if needed, could be a derived class object.
}
CCompoundObject::~CCompoundObject()
{
delete m_pOther;
}
void CCompoundObject::Serialize( CArchive& ar )
{
CObject::Serialize( ar ); // Always call base class Serialize.
m_myob.Serialize( ar ); // Call Serialize on embedded member.
m_pOther->Serialize( ar ); // Call Serialize on objects of known exact type.
// Serialize dynamic members and other raw data
if ( ar.IsStoring() )
{
ar << m_pObDyn;
// Store other members
}
else
{
ar >> m_pObDyn; // Polymorphic reconstruction of persistent object
//load other members
}
}
つまり、シリアル化可能クラスで埋め込み CObject をメンバとして定義している場合は、CArchive 演算子 << および >> を使用できないので、Serialize 関数を呼び出す必要があります。また、シリアル化可能クラスのメンバとして CObject (またはその派生オブジェクト) へのポインタが定義されていても、そのオブジェクトが自身のコンストラクタによって生成されるときも、Serialize 関数を呼び出す必要があります。