Оригинальный DVD-ROM: eXeL@B DVD !
eXeL@B ВИДЕОКУРС !

ВИДЕОКУРС ВЗЛОМ
выпущен 2 июня!


УЗНАТЬ БОЛЬШЕ >>
Домой | Статьи | RAR-cтатьи | FAQ | Форум | Скачать | Видеокурс
Новичку | Ссылки | Программирование | Интервью | Архив | Связь

ПРОГРАММИРОВАНИЕ НА C и С++



Давно заметил, что всё-таки языки С/C++ это не самый лучший вариант программирования под Windows. Сейчас появилась масса более современных и удобных языков, например тот же Python - кроссплатформенный язык, очень легок в изучение. Я его изучил буквально за несколько дней по этому курсу - ссылка. Автор постарался, там видеоуроки на удивление легкие и понятные.

Visual C++.NET
Урок 29. Сериализация в классе

Рассмотрим такую задачу - вы создали приложение с использованием архитектуры Документ-Вид. При этом ваши данные организованы весьма сложно - это значит, что для них надо создавать собственный класс. В классе документа вы объявляете экземпляр этого класса - и тут встает вопрос о том, как данные этого класса читать и записывать из и в файл. Проблема состоит еще в том, что записывать из вашего класса в файл вы хотите не все данные, а только те, которые нужно.

Как вы знаете, для этого служит метод Serialize класса документа. В нем, конечно, можно написать что-то вроде:

// CtestmfcDoc serialization
 
 void CtestmfcDoc::Serialize(CArchive& ar)
 
 {
 
   if (ar.IsStoring())
 
   {
 
     // TODO: add storing code here
 
     ar<<m_Data.m_nAge;
 
     ar<<m_Data.m_sName;
 
 
 
   }
 
   else
 
   {
 
     // TODO: add loading code here
 
     ar>>m_Data.m_nAge;
 
     ar>>m_Data.m_sName;
 
   }
 
 }

Тут мы предполагаем, что переменная m_Data имеет тип нашего класса для данных и в ней есть 2 открытые переменные с данными - m_nAge и m_sName.

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

Поэтому сейчас мы рассмотрим, как поставленную задачу решать правильно. А именно, наш класс данных CData сам будет определять, что в нем надо сериализовывать. Тогда, как вы увидите, и метод Serialize для класса документа будет выглядеть совсем просто.

Итак, создайте с помощью мастера SDI-приложение с поддержкой архитектуры Документ-Вид. Все параметры можно оставить без изменения. Пусть для определенности наш проект называется testmfc.

Добавьте в проект класс для данных CData. Ниже приводятся текст заголовочного файла и файла реализации для этого класса.

Заголовочный файл:

#pragma once
 
 #include "afx.h"
 
 //Наш класс должен быть потомком класса CObject.
 
 class CData :
 
   public CObject
 
 {
 
 public:
 
   //Объявляем метод для сериализации класса.
 
   void Serialize(CArchive& ar);
 
   CData(void);
 
   ~CData(void);
 
   CString m_sName;
 
   //Данные класса.
 
   int m_nAge;
 
   int m_nSomeData;
 
   //Необходимый для сериализации макрос.
 
   DECLARE_SERIAL(CData)
 
 };

Файл реализации:

#include "StdAfx.h"
 
 #include "data.h"
 
 //Необходимый для сериализации макрос.
 
 IMPLEMENT_SERIAL(CData, CObject, VERSIONABLE_SCHEMA | 1)
 
 CData::CData(void)
 
 {
 
 }
 
 CData::~CData(void)
 
 {
 
 }
 
 //Наша реализация сериализации.
 
 //Сериализуем только нужные нам данные.
 
 void CData::Serialize(CArchive& ar)
 
 {
 
   if (ar.IsStoring())
 
     {
 
       // TODO: add storing code here
 
       ar<<m_nAge;
 
       ar<<m_sName;
 
     }
 
     else
 
     {
 
       // TODO: add loading code here
 
       ar>>m_nAge;
 
       ar>>m_sName;
 
     }
 
 }

Немного комментария по коду. Для того, чтобы наш класс стал сериализуемым, мы должны сделать четыре действия:

Во-перых, объявить наш класс потомком класса CObject.

Во-вторых, в заголовочный файл класса вставить макрос DECLARE_SERIAL(...). Его единственный параметр - это имя нашего класса.

В-третьих, в файл реализации вставить макрос IMPLEMENT_SERIAL(CData, CObject, VERSIONABLE_SCHEMA | 1). Его первый параметр - это имя нашего класса, второй - имя его предка, а третий параметр нужен для того, чтобы можно было работать с разными вариантами сериализации (это, например, может оказаться полезным при работе со старыми версиями файлов).

В-четвертых, в классе надо написать свой вариант метода Serialize(CArchive& ar). Этот метод есть в классе CObject и мы должны его переопределить. Так вот, как раз в реализации этого метода мы и должны написать, что наш класс должен сохранять в файле, а что не должен. Обратите внимание, что в нашей реализации мы записываем и читаем только те переменные класса, которые хотим сохранять (m_nAge и m_sName).

С классом CData все. Теперь посмотрим, как этот класс будет работать в нашей программе. Добавьте экземпляр класса в класс документа:

class CtestmfcDoc : public CDocument
 
 {
 
   ...
 
 public:
 
   // Данные.
 
   CData m_Data;
 
 };

В методе OnNewDocument задайте начальные значения для наших данных:

BOOL CtestmfcDoc::OnNewDocument()
 
 {
 
   ...
 
   m_Data.m_nAge=23;
 
   m_Data.m_nSomeData=55;
 
   m_Data.m_sName="Irina";
 
   return TRUE;
 
 }

В классе вида напишите код для изменения и отображения данных класса документа:

void CtestmfcView::OnLButtonDown(UINT nFlags, CPoint point)
 
 {
 
   // TODO: Add your message handler code here and/or call default
 
   CtestmfcDoc* pDoc = GetDocument();
 
   ASSERT_VALID(pDoc);
 
   //Изменяем данные.
 
   pDoc->m_Data.m_nAge++;
 
   pDoc->m_Data.m_nSomeData++;
 
   pDoc->m_Data.m_sName="Igor";
 
   Invalidate();
 
   CView::OnLButtonDown(nFlags, point);
 
 }
void CtestmfcView::OnDraw(CDC* pDC)
 
 {
 
   CtestmfcDoc* pDoc = GetDocument();
 
   ASSERT_VALID(pDoc);
 
   // TODO: add draw code for native data here
 
   //Выводим данные.
 
   CString s;
 
   s.Format("%d", pDoc->m_Data.m_nAge);
 
   pDC->TextOut(10, 10, s);
 
   s.Format("%d", pDoc->m_Data.m_nSomeData);
 
   pDC->TextOut(10, 30, s);
 
   pDC->TextOut(10, 50, pDoc->m_Data.m_sName);
 
 }

И, наконец, самое главное. Реализация метода Serialize в классе документа (сравните с реализацией в начале урока):

void CtestmfcDoc::Serialize(CArchive& ar)
 
 {
 
   //Сериализация данных.
 
   m_Data.Serialize(ar);
 
   if (ar.IsStoring())
 
   {
 
     ...
 
 }

Как вы видите, вся сериализация свелась к одной строке.

Компилируйте и запускайте программу. Сначала при запуске программа покажет данные 23, 55 и Irina:

Данные при запуске.

Если щелкнуть в окне мышкой, то данные изменятся на 24, 56 и Igor:

Данные после изменения.

Сохранияем документ, закрываем программу, потом снова запускаем и открываем сохраненный документ. При этом покажутся данные 24, 55 и Igor:

Данные после сохранения.

Обратите внимание, что сохранились только данные, задаваемые переменными m_nAge и m_sName (24 и Igor) класса CData, а данные, относящиеся к переменной m_nSomeData (56), не сохранились. Это потому, что мы так сделали в методе Serialize класса CData.



<< ВЕРНУТЬСЯ В ПОДРАЗДЕЛ

<< ВЕРНУТЬСЯ В ОГЛАВЛЕНИЕ




Материалы находятся на сайте https://exelab.ru/pro/



Оригинальный DVD-ROM: eXeL@B DVD !


Вы находитесь на EXELAB.rU
Проект ReactOS