Поделиться через


Сериализация: создание сериализуемого класса

Замечание

Библиотека классов Microsoft Foundation (MFC) продолжает поддерживаться. Однако мы больше не добавляем функции или обновляем документацию.

Для сериализации класса необходимо выполнить пять основных шагов. Они перечислены ниже и описаны в следующих разделах:

  1. Производный класс от CObject (или от какого-либо класса, производного от CObject).

  2. Переопределение функции-члена Serialize.

  3. Использование макроса DECLARE_SERIAL в объявлении класса.

  4. Определение конструктора, который не принимает аргументов.

  5. Использование макроса IMPLEMENT_SERIAL в файле реализации для класса.

Если вы вызываете Serialize напрямую, а не через >> и << операторы CArchive, последние три шага не требуются для сериализации.

Извлечение класса из CObject

Базовый протокол сериализации и функциональные возможности определяются в CObject классе. Производя наследование вашего класса от CObject (или от класса, производного от CObject), как показано в следующем объявлении класса CPerson, вы получаете доступ к протоколу сериализации и функциональным возможностям CObject.

Переопределение функции-члена сериализации

Функция-член Serialize , определенная в CObject классе, отвечает за фактические сериализацию данных, необходимых для записи текущего состояния объекта. Функция Serialize имеет CArchive аргумент, который используется для чтения и записи данных объекта. Объект CArchive имеет функцию-член IsStoring, которая указывает, производится ли хранение (запись данных) или загрузка (чтение данных). Используя результаты 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

  1. Вызовите версию Serialize базового класса, чтобы убедиться, что наследуемая часть объекта сериализуется.

  2. Вставьте или извлеките переменные-члены, относящиеся к классу.

    Операторы вставки и извлечения взаимодействуют с архивным классом для чтения и записи данных. В следующем примере показано, как использовать 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 требуется конструктор по умолчанию для повторного создания ваших объектов во время их десериализации (процесса, который включает загрузку с диска). Процесс десериализации заполняет все переменные-члены значениями, необходимыми для повторного создания объекта.

Этот конструктор может быть объявлен общедоступным, защищенным или закрытым. Если вы сделаете его защищенным или закрытым, вы помогаете гарантировать, что он будет использоваться исключительно функциями сериализации. Конструктор должен поместить объект в состояние, позволяющее удалить его при необходимости.

Замечание

Если вы забыли определить конструктор без аргументов в классе, использующего макросы DECLARE_SERIAL и IMPLEMENT_SERIAL, вы получите предупреждение компилятора "нет конструктора по умолчанию" в строке, где используется макрос IMPLEMENT_SERIAL.

Использование макроса IMPLEMENT_SERIAL в файле реализации

Макрос IMPLEMENT_SERIAL используется для определения различных функций, необходимых при создании производного класса от сериализуемого CObject. Этот макрос используется в файле реализации (. CPP) для класса. Первые два аргумента макроса — это имя класса и имя его немедленного базового класса.

Третий аргумент этого макроса — это номер схемы. Номер схемы по сути является номером версии для объектов класса. Используйте целое число больше или равно 0 для номера схемы. (Не путайте этот номер схемы с терминологией базы данных.)

Код сериализации MFC проверяет номер схемы при чтении объектов в память. Если номер схемы объекта на диске не соответствует номеру схемы класса в памяти, библиотека вызовет исключение CArchiveException, предотвращающее чтение неправильной версии объекта в программе.

Если вы хотите, чтобы функция-член Serialize могла читать несколько версий , то есть файлы, написанные с разными версиями приложения, можно использовать значение VERSIONABLE_SCHEMA в качестве аргумента для макроса IMPLEMENT_SERIAL. Сведения об использовании и пример см. в GetObjectSchema функции-члене класса CArchive.

В следующем примере показано, как использовать IMPLEMENT_SERIAL для класса, CPersonкоторый является производным от CObject:

IMPLEMENT_SERIAL(CPerson, CObject, 1)

После создания сериализуемого класса можно сериализовать объекты класса, как описано в статье Сериализация: сериализация объекта.

См. также

сериализация