Студопедия

КАТЕГОРИИ:

АвтоАвтоматизацияАрхитектураАстрономияАудитБиологияБухгалтерияВоенное делоГенетикаГеографияГеологияГосударствоДомЖурналистика и СМИИзобретательствоИностранные языкиИнформатикаИскусствоИсторияКомпьютерыКулинарияКультураЛексикологияЛитератураЛогикаМаркетингМатематикаМашиностроениеМедицинаМенеджментМеталлы и СваркаМеханикаМузыкаНаселениеОбразованиеОхрана безопасности жизниОхрана ТрудаПедагогикаПолитикаПравоПриборостроениеПрограммированиеПроизводствоПромышленностьПсихологияРадиоРегилияСвязьСоциологияСпортСтандартизацияСтроительствоТехнологииТорговляТуризмФизикаФизиологияФилософияФинансыХимияХозяйствоЦеннообразованиеЧерчениеЭкологияЭконометрикаЭкономикаЭлектроникаЮриспунденкция

Создание класса, обеспечивающего сохранение-восстановление объектов




Что произойдет, если вы создадите свой собственный класс, объект которого войдет в документ? Как сделать этот объект живучим (в оговоренном выше смысле)?

Предположим, что вы хотите усовершенствовать приложение My таким образом, чтобы для хранения данных документа использовался объект изобретенного вами класса CMessages. Пусть теперь член класса документа, в котором содержатся данные, называется m_messages и он является экземпляром класса CMessages. Этот класс содержит три объекта класса CStгing, каждый из которых должен сохраняться и восстанавливаться при сохранении и загрузке документа. Первый способ обеспечить такую возможность — индивидуально сохранять и восстанавливать каждую отдельную строку. Текст соответствующей программы представлен ниже

void СMyDoc::Serialize(CArchive& ar)

{

if (ar. IsStoring())

{

ar << m_messages.m_message1;

ar << m_messages.m_message2;

ar << m_messages.m_message3;

}

else

ar >> m_essages.m_essagel;

ar >> m_messages.m_message2;

ar >> m_messages.m_message3;

Такую программу можно написать в том случае, если, во-первых, все три члена класса CMessages являются открытыми (объявлены как publiс) и, во-вторых, известна реализация самого класса. Если в дальнейшем класс CMessages будет некоторым образом изменен, придется переписать и эту функцию. Если же вы до конца верны моральному кодексу строителя объектно-ориентированных программ, то непременно согласитесь, что функции сохранения и восстановления данных должны быть инкапсулированы в самом классе CMessages. Конечно, это потребует определенной предварительной подготовки. Основные этапы создания класса, который может самостоятельно организовать сохранение-восстановление (в документации на MFC применяется термин serialise — сериализация) собственных членов-переменных, перечислены ниже.

1. Объявите класс как производный от CObject.

2.В объявление класса включите макрос DECLARE SERIAL.

3. В реализацию класса включите макрос IMPLEMENT_SERIAL.

4. Перегрузите метод Serialize(), унаследованный от базового класса.

5. Объявите для нового класса среди прочих "пустой" конструктор по умолчанию.

Далее мы проанализируем приложение, в котором именно по этойсхемесоздаются объекты, обладающие свойством живучести.

 

Изменим приложение My следующим образом. Класс документа будет содержать класс CMessages. Это приложение будет иметь команду меню Edit->Change Messages, которая изменяет все три строки. Новая программа сможет сохранять и восстанавливать документы, для чего будут использованы пункты Save и Open меню File.

Добавьте в секцию атрибутов класса документа определение переменной, чтобы этот фрагмент файла MyDoc.h выглядел следующим образом:

//Атрибуты.

public:

CMessages m_messages;

Следующий шаг—создание класса CMessages.

Для создания этого класса нужно выбрать в меню среды разработки Insert->New Class. В поле со списком Class type диалогового окна New Class выберите Generic Class (порождающий класс). В поле Name введите имя нового класса CMessages. Ниже введите имя базового класса Cobject, а в столбце As оставьте предлагаемую по умолчанию установку publiс.

В результате будут созданы два файла— файл заголовка Messages.h и файл реализации Messages.срр. В каждый из них будут введены заготовки программного кода. Возможно, будет выведено предупреждающее сообщение о том, что среда разработки не может найти файл заголовка для класса CObject. Если такое случится, можете смело щелкать на ОК, поскольку все системные файлы заголовков MFC всегда доступны компилятору без включения директив. Переключитесь в окне редактора кода на файл MyDoc.h и добавьте в него перед определением класса директиву:

#include "Messages.h"

В результате при трансляции класса документа компилятору будет доступно определение класса CMessages. Теперь вернитесь к тексту в файле Messages.h и добавьте следующие строки:

DECLARE SERIAL(CMessages)

protected:

CString m_message1;

CString m_message2;

CString m_message3;

public:

void SetMessage(UINT msgNum, CString msg);

CString GetMessage(UINT msgNum);

void Serialize(CArchive& ar);

Макрос DECLARE_SERIAL() обеспечивает выполнение ряда дополнительных функций — MFC использует этот макрос для того, чтобы включить в определение класса объявления дополнительных членов (переменных и функций), которые необходимы для реализации живучести объектов класса.

Далее объявлены члены-переменные класса: три объекта класса CString. Обратите внимание, что они объявлены как защищенные — protected. Следующими идут открытые (public) функции-члены. SetMessage() имеет два аргумента — индекс строки, в которую заносятся данные, и собственно записываемая строка символов. Эта функция позволяет изменить состояние объекта класса. GetMessage()— это сопряженная с предыдущей функция, которая позволяет программе прочесть содержимое любой строки объекта. Ее единственный аргумент— индекс считываемой строки. И наконец, в нашем классе перегружается метод Serialize(). Эта функция — сердце живучего объекта. Реализация ее уникальна для каждого класса.

 

Файл Messages.cpp— реализация методов класса CMessages

 


Void CMessages::SetMessage(UINT msgNum, CString msg)

{

switch (msgNum)

{

case 1:

m_message1=msg;

break;

case 2:

m_message2 = msg;

break;

case 3:

m_message3 = msg;

break;

}

}

CString CMessages::GetMessage(UINT msgNum)

{

switch (msgNum)

{

case 1:

return m_message1;

case 2:

return m_message2;

case 3:

eturn m_message3;

default:

return "";

}

}

void CMessages::Serialize(CArchive& ar)

{

CObject::Serialize(ar);

if (ar.IsStoring())

{

ar << m_message1 << m_message2 << m_message3;

}

else

{

ar >> m_message1 >> m_message2 >> m_message3;

}

}


Функции SetMessage() и GetMessage() простым способом реализуют то, что от них требуется. Рассмотрим функцию Serialize(). Обратите внимание на то, что первый оператор в теле функции— это вызов одноименного метода базового класса CObject. Это стандартный прием, который используется во многих функциях, перегружающих одноименные функции базового класса. В данном случае — это просто дань дисциплине, поскольку метод CObject::Serialize() ничего не выполняет (он пуст). Но, тем не менее, воспитайте в себе привычку всегда вызывать одноименный метод класса-родителя, поскольку не всегда класс происходит прямо от CObject (является прямым наследником CObject) и неизвестно, что делает Serialize() в каком-нибудь другом классе, ребенком которого вы решите объявить свой класс.

После вызова родительской версии Serialize() сохраняет или восстанавливает данные также, как мы это делали в классе документа. Поскольку члены данных, которые нужно сохранять-восстанавливать, есть объекты класса CString, можно использовать терминальные операторы >> и << для передачи данных на диск и с диска.

В самом начале файла Messages.срр после директив include вставьте строку IMPLEMENT_SERIAL(CMessages, CObject,0)

Макрос IMPLEMENT_SERIAL() сопряжен с DECLARE_SERIAL(). Он обеспечивает реализацию функций, которые и обеспечивают живучесть объектов класса. Три аргумента макроса (имя класса, имя класса-родителя и номер схемы (schema number)) — это нечто вроде номера версии. В большинстве случаев в качестве номера схемы можно задавать 0 или 1.










Последнее изменение этой страницы: 2018-04-12; просмотров: 269.

stydopedya.ru не претендует на авторское право материалов, которые вылажены, но предоставляет бесплатный доступ к ним. В случае нарушения авторского права или персональных данных напишите сюда...