总的来说,序列化作用是把MFC中的所有对象都存储到硬盘上(storing)或者从硬盘上的数据创建相应的对象(loading)。
Serialization的逻辑结构:
要是一个类能够序列化,则该类须直接或间接派生自CObject并且要包含宏DECLARE_SERIAL(在类的Declaration中)和IMPLEMENT_SERIAL(在类的Implement中)。
Serial函数
假设类CStudent的声明中有如下代码:
public:
CString m_strName;
int m_nGrade;
CString m_strName;
int m_nGrade;
它的Serial函数也许就是:
void CStudent::Serialize(CArchive& ar)
{
TRACE("Entering CStudent::Serialize\n");
if (ar.IsStoring()) {
ar << m_strName << m_nGrade;
}
else {
ar >> m_strName >> m_nGrade;
}
}
{
TRACE("Entering CStudent::Serialize\n");
if (ar.IsStoring()) {
ar << m_strName << m_nGrade;
}
else {
ar >> m_strName >> m_nGrade;
}
}
IsStoring函数用来判断是在Storing还是在Loading。“<<”是Insertion运算符,使用值参数;“>>”是extraction运算符,使用引用参数。
如果CStudent派生自CPerson(或者其他),则还要调用CPerson::Seralize。但无需调用CObject::Serialize,因为它什么东西都不做。
Loading Embeded Objects and Pointers
Embeded Objects
比如在上述在CStudent声明中又有:
public:
CTranscript m_transcript;
CTranscript m_transcript;
则它的Serialize函数应为:
void CStudent::Serialize(CArchive& ar)
{
if (ar.IsStoring()) {
ar << m_strName << m_nGrade;
}
else {
ar >> m_strName >> m_nGrade;
}
m_transcript.Serialize(ar);
}
{
if (ar.IsStoring()) {
ar << m_strName << m_nGrade;
}
else {
ar >> m_strName >> m_nGrade;
}
m_transcript.Serialize(ar);
}
也就是说直接调用Embeded Objects的Serialize函数。
Embeded Pointers
序列化Embeded Pointers有两种方法。
可以先先New一个对象指针赋给Embeded Pointers,然后调用Serialize函数
例如:
在CStudent声明中有:
public:
CTranscript* m_pTranscript;
CTranscript* m_pTranscript;
Serialize函数可以为:
void CStudent::Serialize(CArchive& ar)
{
if (ar.IsStoring())
ar << m_strName << m_nGrade;
else {
m_pTranscript = new CTranscript;
ar >> m_strName >> m_nGrade;
}
m_pTranscript->Serialize(ar);
}
{
if (ar.IsStoring())
ar << m_strName << m_nGrade;
else {
m_pTranscript = new CTranscript;
ar >> m_strName >> m_nGrade;
}
m_pTranscript->Serialize(ar);
}
第二种方法是:
void CStudent::Serialize(CArchive& ar)
{
if (ar.IsStoring())
ar << m_strName << m_nGrade << m_pTranscript;
else
ar >> m_strName >> m_nGrade >> m_pTranscript;
}
{
if (ar.IsStoring())
ar << m_strName << m_nGrade << m_pTranscript;
else
ar >> m_strName >> m_nGrade >> m_pTranscript;
}
序列化Collections
如果调用序列化例如CStudent的CObList Collection,那么每个CStudent的Serialize函数将依次被调用。
关于Loading Collection的一些细节:
1、如果Collection包含着不同类的指针,那么每个类的名字将被存储以便被创建;
2、如果一个对象里面包含一个Collection,那么在调用Serialize之前须清空Collection。如在Document中调用DeleteContents。
3、从Archive中load一个Collection有以下步骤:
a、识别对象的类名;
b、在堆中给对象分配空间;
c、把对象的数据存入分配的空间中;
d、把指向新对象的指针存入Collection中。