Almacenar y cargar CObjects a través de un archivo
Almacenar y cargar CObject
s a través de un archivo requiere una atención especial. En ciertos casos, debe llamar a la función Serialize
del objeto, en la que el objeto CArchive
es un parámetro de la llamada a Serialize
, en contraposición con el uso del operador << o >> del objeto CArchive
. El hecho importante que hay que tener en cuenta es que el operador >> del objeto CArchive
operador construye el objeto CObject
en memoria en función de la información de CRuntimeClass
que el archivo de almacenamiento escribe previamente en el archivo.
Por lo tanto, usar los operadores << y >> del objeto CArchive
, en vez de llamar a Serialize
, depende de si necesita que el archivo de carga reconstruya dinámicamente el objeto en función de la información de CRuntimeClass
que se almacenó previamente. Use la función Serialize
en estos casos:
Cuando deserializa el objeto, conoce la clase exacta del objeto de antemano.
Cuando deserializa el objeto, ya le tiene asignada memoria.
Precaución
Si carga el objeto mediante la función Serialize
, también debe almacenarlo mediante la función Serialize
. No lo almacene con el operador << de CArchive
y luego cargue con la función Serialize
, ni lo almacene con la función Serialize
y luego cargue con el operador CArchive >>
.
En el ejemplo siguiente, se muestran los casos:
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
}
}
En resumen, si la clase serializable define un objeto CObject
como miembro, no debe usar los operadores << y >> de CArchive
para dicho objeto, sino que debe llamar a la función Serialize
. Además, si la clase serializable define un puntero a un CObject
(o un objeto derivado de CObject
) como miembro, pero construye este otro objeto en su propio constructor, también se debe llamar a Serialize
.