序列化是 MFC 文檔/視圖架構的核心功能之一,實現資料在記憶體與檔案之間的雙向轉換。本文通過三個漸進式範例(Memo、PHN、ARCH),系統講解基本數據序列化、CObList 管理的 C++ 對象列表序列化,以及完全自定義的 CArchive 使用技巧。
CFormView,三個編輯框對應三個 CString 變數。GetDocument() 同步。OnNewDocument(),視圖初始化在 OnInitialUpdate()。// 文檔類
void CMemoDoc::Serialize(CArchive& ar) {
if (ar.IsStoring())
ar << m_strData1 << m_strData2 << m_strData3;
else
ar >> m_strData1 >> m_strData2 >> m_strData3;
}
選單「檔案/儲存」即自動觸發序列化,框架處理「是否儲存修改」提示。
class CPhone : public CObject {
DECLARE_SERIAL(CPhone)
public:
CString m_strName, m_strPhone;
CPhone() {} // 必須有無參數建構函式
virtual void Serialize(CArchive& ar) {
if (ar.IsStoring()) ar << m_strName << m_strPhone;
else ar >> m_strName >> m_strPhone;
}
};
IMPLEMENT_SERIAL(CPhone, CObject, 0) // 版本號 0
class CPHNDoc : public CDocument {
CObList m_PhoneList; // 可公開或提供 GetPhoneList()
protected:
virtual void DeleteContents() {
while (!m_PhoneList.IsEmpty())
delete m_PhoneList.RemoveHead(); // 釋放記憶體
}
virtual void Serialize(CArchive& ar) {
m_PhoneList.Serialize(ar); // 一行搞定列表序列化
}
};
前提條件:CPhone 必須繼承 CObject、擁有無參數建構函式、實作 Serialize、使用 DECLARE_SERIAL/IMPLEMENT_SERIAL。
POSITION m_pos; CObList* m_pList;OnInitialUpdate 取得文檔列表頭部位置,讀取第一筆資料填入介面。EN_CHANGE 通過 UpdateData(TRUE) 回寫文檔對象並 SetModifiedFlag()。GetPrev/GetNext 更新 m_pos 並刷新介面。m_pos = m_pList->AddTail(new CPhone());刪除:delete m_pList->RemoveAt(m_pos) 並處理空列表情況。不依賴「檔案/儲存」選單,手動建立 CFile + CArchive 實現指定路徑存取:
// 存檔
CFile f; f.Open(_T("c:\\arc.arc"), CFile::modeCreate|CFile::modeWrite);
CArchive ar(&f, CArchive::store);
ar << m_var1 << m_var2;
ar.Close(); f.Close();
// 讀檔
CFile f; if (!f.Open(_T("c:\\arc.arc"), CFile::modeRead)) return;
CArchive ar(&f, CArchive::load);
ar >> m_var1 >> m_var2;
ar.Close(); f.Close();
UpdateData(FALSE);
適用於設定檔、快照、網路傳輸等非標準文檔流程。
IMPLEMENT_SERIAL 第三參數為 schema number,升級資料結構時遞增,並在 Serialize 內用 ar.GetObjectSchema() 兼容舊版。CObList 儲存指標時,序列化會自動保存動態類型,反序列化還原正確派生類對象。DeleteContents 必須 delete 每個元素,否則文檔關閉/新建時洩漏。try/catch(CArchiveException*) 中。0xFF 0xFE (UTF-16LE BOM) 可避免中文亂碼。MFC 序列化機制強大且靈活:基本類型直接 <</>>,對象列表交給 CObList::Serialize,特殊需求可手動操控 CArchive。掌握 DECLARE_SERIAL/IMPLEMENT_SERIAL、無參數建構函式、DeleteContents 清理三大要素,即可在專案中穩健實現資料持久化。