總的來說,序列化作用是把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中。