На этом шаге мы рассмотрим процесс сериализации.
Напомним, что данные приложения сохраняются в объекте документа. Эти данные сериализуются в дисковый файл документа, а затем восстанавливаются в этот объект. Тип файла Вы связываете с приложением, задав расширения в диалоговом окне Advanced Options в окне 4 мастера АррWizard (смотри 2 шаг).
Объект документа начинает сериализацию данных приложения в ответ на выбор пользователем соответствующих команд из меню работы с файлами. Каркас создает объект CArchive надлежащего типа (в зависимости от того, сохраняются или восстанавливаются архивные данные) и передает его в качестве параметра в функцию документа Serialize().
Мастер AppWizard создает в классе документа на месте Serialize() функцию-заглушку, которую требуется "наполнить" кодом, отвечающим за сохранение и восстановление постоянных членов-данных. Простыми членами-данными можно манипулировать, применяя операторы << и >>. Если в документе есть более сложные объекты, в которых предусмотрена собственная сериализация, Вы обязаны вызвать для них соответствующие функции Serialize(), передавая ссылку на текущий архив.
В качестве примера рассмотрим приложение TestАрр, в котором имеется класс документа с тремя членами-данными:
Class CTestAppDoc { CString m_string; DWORD m_dwVar; MyObj m_obj; }
Допустим, что MyObj - класс, поддерживающий сериализацию. В приведенном ниже коде показан пример функции Serialize() для класса документа TestApp:
void CTestAppDoc::Serialize(CArchive& ar) { if (ar.IsStoring()) { ar << m_string; ar << m_dwVar; } else { ar >> m_string; ar >> m_dwVar; } m_obj.Serialize(ar); }
Обратите внимание, что функция MyObj::Serialize() вызывается из операторов условного перехода - в ней самой заданы условия ветвления в зависимости от режима работы с данными (записи или чтения). На рисунке 1 показано, как можно применить эту методику для рекурсивной сериализации.
Рис.1. Сериализация объектов в контейнере
Непротиворечивость процедур сериализации гарантирует упрощение манипуляций со сложными объектами - с сохранением их на диске и обратным восстановлением в приложении. Вы обязаны обеспечить соответствие сохраняющих и восстанавливающих ветвей Вашей функции Serialize() - они должны работать с одними и теми же объектами и в одном и том же порядке.
Процедуры сериализации гарантируют корректную "реконструкцию" структуры объекта при ее восстановлении из дискового файла. Это обеспечивается сохранением сведений не только о типе объекта, но и о его текущем состоянии (значениях членов-данных). При восстановлении соответствующая процедура использует эту информацию для определения типа и создания объекта, принимающего данные. Тем не менее Вам надо гарантировать корректность создания объекта, предоставив для своего сериализуемого класса конструктор по умолчанию (без параметров).
На следующем шаге мы рассмотрим пример сериализации данных в приложении.