序列化:建立可序列化的類別
製作可序列化類別需要進行五個主要步驟。 以下會列出這些步驟,並在下列各節進行說明:
如果您直接呼叫 Serialize
而不是透過 >> CArchive 的 和 << 運算子,則序列化不需要最後三個步驟。
從 CObject 衍生類別
基本序列化通訊協定和功能會在 CObject
類別中定義。 藉由從 CObject
(或從衍生自 CObject
的類別) 衍生您的類別 (如下列類別 CPerson
的宣告),您可以取得 CObject
的序列化通訊協定和功能的存取權。
覆寫序列化成員函式
Serialize
成員函式 (在 CObject
類別中定義) 會負責實際序列化擷取物件目前狀態所需的資料。 Serialize
函式具有一個 CArchive
引數,用來讀取和寫入物件資料。 CArchive 物件具有成員函式, IsStoring
指出是 Serialize
儲存(寫入資料)還是載入(讀取資料)。 使用 做為輔助線的結果 IsStoring
,您可以使用插入運算子在 物件中 CArchive
插入物件的資料(),或使用擷取運算子 ( << >> ) 來擷取資料。
請考慮衍生自 CObject
的類別,而且有兩個新的成員變數,類型 CString
與 WORD 。 下列類別宣告片段顯示新成員變數和覆寫 Serialize
成員函式的宣告:
class CPerson : public CObject
{
public:
DECLARE_SERIAL(CPerson)
// empty constructor is necessary
CPerson();
virtual ~CPerson();
CString m_name;
WORD m_number;
void Serialize(CArchive& archive);
};
覆寫序列化成員函式
呼叫
Serialize
的基底類別版本來確保已序列化物件的繼承部分。插入或擷取類別專屬的成員變數。
插入和擷取運算子會與封存類別互動,以讀取和寫入資料。 下列範例將說明如何為先前宣告的
Serialize
類別實作CPerson
。void CPerson::Serialize(CArchive& archive) { // call base class function first // base class is CObject in this case CObject::Serialize(archive); // now do the stuff for our specific class if (archive.IsStoring()) archive << m_name << m_number; else archive >> m_name >> m_number; }
您也可以使用 CArchive::Read 和 CArchive::Write 成員函式來讀取和寫入大量不具類型的資料。
使用 DECLARE_SERIAL 宏
在支援序列化的類別宣告中,需要DECLARE_SERIAL宏,如下所示:
class CPerson : public CObject
{
public:
DECLARE_SERIAL(CPerson)
使用無引數定義建構函式
MFC 在還原序列化以重新建立您的物件時 (從磁碟載入),需要一個預設的建構函式。 還原序列化程序需要填入所有重新建立物件所需的成員變數值。
這個建構函式可以宣告為 public、protected 或 private。 將其設定為 protected 或 private 有助於確保該函式只能由序列化函式使用。 建構函式必須讓物件處於可視需要刪除的狀態。
注意
如果您忘記在使用DECLARE_SERIAL和IMPLEMENT_SERIAL宏的類別中定義沒有引數的建構函式,您將會在使用IMPLEMENT_SERIAL宏的行上收到「沒有可用的預設建構函式」編譯器警告。
在實作檔案中使用 IMPLEMENT_SERIAL 宏
當您從 CObject
衍生可序列化類別時,會使用 IMPLEMENT_SERIAL 宏來定義所需的各種函式。 您會在實作檔 (.CPP) 中為您的類別使用這個巨集。 巨集的前兩個引數為類別的名稱及其即時基底類別的名稱。
這個巨集的第三個引數是結構描述編號。 結構描述數目基本上是類別之物件的版本號碼。 結構描述編號使用大於或等於 0 的整數 (請勿將這個結構描述編號與資料庫詞彙混淆)。
將物件讀取至記憶體時,MFC 序列化程式碼會檢查結構描述編號。 如果磁碟上物件的結構描述編號與記憶體中類別的結構描述編號不相符,程式庫會擲回 CArchiveException
,防止您的程式讀取不正確版本的物件。
如果您希望 Serialize
成員函式能夠讀取多個版本,也就是以不同版本的應用程式撰寫的檔案,您可以使用值 VERSIONABLE_SCHEMA 做為IMPLEMENT_SERIAL宏的引數。 如需使用方式的詳細資訊和範例,請參閱類別 GetObjectSchema
的 CArchive
成員函式。
下列範例示範如何將 IMPLEMENT_SERIAL 用於衍生自 CObject
的類別 CPerson
:
IMPLEMENT_SERIAL(CPerson, CObject, 1)
擁有可序列化類別之後,您可以序列化 類別的物件,如序列化:序列化物件 一文 所述。