Электронная библиотека книг Александра Фролова и Григория Фролова.
Shop2You.ru Создайте свой интернет-магазин
Библиотека
Братьев
Фроловых

Microsoft visual C++ и MFC

© Александр Фролов, Григорий Фролов
Том 24, М.: Диалог-МИФИ, 1993.

[Назад] [Содеожание] [Дальше]

Класс CObject - основной класс MFC

Подавляющее большинство классов из библиотеки MFC наследуются от основного класса CObject XE "CObject" . Практически все классы, которые используются в ваших приложениях, например CView или CWinApp, унаследованы от класса CObject.

Класс CObject обеспечивает наиболее общие свойства всех других классов. Так, класс CObject позволяет сохранять и восстанавливать состояние объектов, порожденных из данного класса. Например, текущее состояние объекта можно записать в файл на диске, а затем восстановить объект из этого файла. Этот процесс иногда называют преобразованием в последовательную форму (serialization).

Для объектов, порожденных от CObject, можно получить информацию во время работы программы. Такая возможность используется при динамическом создании объектов. MFC версии 4.0 позволяет также определить имя типа объекта во время работы программы. Эта особенность называется Run-Time Type Information XE "Run-Time Type Information" (RTTI XE "RTTI" ). Кроме того возможности класса CObject используются для вывода диагностических сообщений объектами, порожденными от этого класса.

Класс CObject не позволяет осуществлять множественное наследование. Ваш класс должен иметь только один базовый класс CObject.

Чтобы приложение смогло воспользоваться всеми возможностями класса CObject, необходимо включить в описание и определение класса специальные макрокоманды.

Например, чтобы получить возможность во время выполнения приложения определять название класса и его базовый класс, следует включить в объявление и определение вашего класса макрокоманды DECLARE_DYNAMIC и IMPLEMENT_DYNAMIC. А если вам надо, чтобы состояние объектов класса можно было сохранять и восстанавливать из архивного класса, следует включить в объявление и определение класса макрокоманды DECLARE_SERIAL и IMPLEMENT_SERIAL.

Конструкторы класса

Для класса CObject определены два конструктора. Первый конструктор используется по умолчанию и не имеет параметров. Именно этот конструктор вызывается конструкторами классов, наследованных от CObject:


CObject();

Второй конструктор класса CObject называется конструктором копирования, потому что в качестве параметра objectSrc он принимает ссылку на другой объект этого же класса. Конструктор копирования создает новый объект и выполняет копирование всех элементов объекта, указанного в качестве параметра.

Для класса CObject конструктор копирования описан как private и не имеет определения. Если вы попытаетесь передать по значению объект класса, наследованного от CObject, и не определите конструктор копирования в своем классе, вы получите ошибку на этапе компиляции.

В случае, если бы конструктор копирования класса CObject не был описан, компилятор создал бы его автоматически. Таким образом описание конструктора копирования как private, принуждает вас явно определить конструктор копирования для порожденных классов (конечно если конструктор копирования необходим):


private:
	CObject(const CObject& objectSrc);

Для динамического создания и удаления объектов класса CObject вы можете воспользоваться операторами new и delete. Эти операторы переопределены в классе CObject, однако назначение и основные принципы их работы остались прежними.

Оператор присваивания

Для класса CObject описан оператор присваивания. Он описан с ключевым словом private и не имеет реализации:


private:
    void operator =( const CObject& src );
	

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

Диагностика

Класс CObject содержит методы AssertValid и Dump, которые могут помочь на этапе отладки приложения. Оба эти методы определены как виртуальные. Вы можете переопределить их в своем классе.

Проверка целостности объектов класса

Метод AssertValid XE "CObject:AssertValid" выполняет проверку целостности объекта класса. Он проверяет состояние элементов данных класса на недопустимые значения. Если вы работаете с отладочной версией приложения и метод AssertValid обнаружит ошибку во внутреннем представлении объекта класса, выполнение приложения прерывается с выдачей соответствующего сообщения.

virtual void AssertValid() const;

Если вы наследуете класс от базового класса CObject и желаете использовать возможности метода AssertValid, вы должны переопределить его. Переопределенный метод AssertValid должен вызывать метод AssertValid базового класса, чтобы проверить целостность соответствующей части объекта. Затем необходимо выполнить проверку элементов порожденного класса. Для этого используйте макрокоманду ASSERT:

ASSERT(booleanExpression)

Макрокоманда ASSERT проверяет свой параметр booleanExpression. Если параметр макрокоманды имеет нулевое значение (FALSE), она отображает диагностическое сообщение и прерывает работу приложения. Если параметр booleanExpression не равен нулю (TRUE) работа приложения продолжается и макрокоманда не выполняет никаких действий.

Макрокоманда ASSERT выполняет проверку только в отладочной версии приложения. В окончательной версии приложения, построенной без отладочной информации, макрокоманда ASSERT не работает.

Если проверку параметра макрокоманды необходимо выполнять и в окончательной версии приложения, вы можете использовать вместо макрокоманды ASSERT макрокоманду VERIFY. Но при обнаружении ошибки работа приложения не будет прервана.

Вот пример переопределения метода AssertValid для класса CFigure, наследованного от базового класса CObject:


// Класс CFigure наследуется от базового класса CObject
class	CFigure : public CObject
{
	// Переопределяем виртуальный метод базового класса
	int	m_area = 0;

	// Остальные элементы класса...
}

// Переопределяем виртуальный метод AssertValid класса CObject 
void CFigure::AssertValid() const
{
	// Сначала проверяем целостность элементов базового класса
	CObject::AssertValid();

	// Проверяем элемент m_area. 
	// Он должен быть больше или равен нулю
	ASSERT(m_area >= 0); 
}

Получение дампа объекта класса

Виртуальный метод Dump позволяет получить дамп объекта данного класса:

virtual void Dump(CDumpContext& dc) const;

Метод Dump XE "CObject:Dump" имеет единственный параметр dc, определяющий контекст отображения для вывода дампа объекта. Часто в качестве параметра dc используется предопределенный объект afxDump. Он позволяет передавать информацию в окно отладчика Visual C++. Объект afxDump определен только для отладочной версии приложения.

Вы можете переопределить метод Dump для своего класса. Переопределенный метод должен сначала вызывать метод Dump базового класса, а затем выводить значения элементов самого класса. Для вывода значений элементов объекта класса в контекст dc можно использовать операторы <<, переопределенные для класса CDumpContext.

Если класс определен с макрокомандами IMPLEMENT_DYNAMIC XE "IMPLEMENT_DYNAMIC" или IMPLEMENT_SERIAL XE "IMPLEMENT_SERIAL" , то метод Dump класса CObject будет отображать также имя самого класса.

Для класса CFigure, описанного выше, метод Dump можно определить следующим образом:


void CFigure::Dump(CDumpContext &dc) const
{
	// Вызываем метод Dump базового класса
	CObject::Dump(dc);

	// Выводим в контекст dc значение элемента m_area 
	// класса CFigure
	dc << "Площадь = " << m_area;
}

Сохранение и восстановление состояния объекта

В классе CObject определены метод IsSerializable XE "CObject:IsSerializable" и виртуальный метод Serialize, которые используются для сохранения и восстановления состояния объектов в файлах на диске. Чтобы объекты класса можно было сохранять в файлах на диске с возможностью их последующего восстановления, объявление класса объекта должно содержать макрокоманду DECLARE_SERIAL XE "DECLARE_SERIAL" , а реализация класса макрокоманду IMPLEMENT_SERIAL XE "IMPLEMENT_SERIAL" . Более подробно об сохранении и восстановлении объектов можно прочитать в разделе “Запись и восстановление объектов”.

Метод IsSerializable

Метод IsSerializable позволяет определить, можно ли записать состояние объекта в файле, а потом восстановить его. Если это возможно, метод IsSerializable возвращает ненулевое значение.

BOOL IsSerializable() const;

Виртуальный метод Serialize

Виртуальный метод Serialize XE "CObject:Serialize" вызывается, когда надо сохранить или восстановить объект класса из файла на диске. Вы должны переопределить этот метод в своем классе, чтобы сохранить или восстановить его элементы. Переопределенный метод Serialize должен вызывать метод Serialize базового класса:


virtual void Serialize(CArchive& ar);
	throw(CMemoryException);
	throw(CArchiveException);
	throw(CFileException);

Ниже прототипа метода Serialize мы указали исключения, которые могут быть им вызваны. Более подробно об исключениях вы можете прочитать в разделе “Исключения - класс CException” данной главы.

Информация о классе

Класс CObject содержит два метода: GetRuntimeClass и IsKindOf, позволяющих получить информацию о классе объекта.

Виртуальный метод GetRuntimeClass

Виртуальный метод GetRuntimeClass XE "CObject:GetRuntimeClass" возвращает указатель на структуру CRuntimeClass, описывающую класс объекта, для которого метод был вызван:

virtual CRuntimeClass* GetRuntimeClass() const;

Для каждого класса, наследованного от CObject поддерживается своя структура CRuntimeClass. Если вы желаете использовать метод GetRuntimeClass в своем классе, наследованном от CObject, вы должны поместить в реализации класса макрокоманду IMPLEMENT_DYNAMIC XE "IMPLEMENT_DYNAMIC" или IMPLEMENT_SERIAL XE "IMPLEMENT_SERIAL" .

Структура CRuntimeClass XE "CRuntimeClass" содержит различную информацию о классе. Ниже перечислены несколько основные полей этой структуры.

Поле структуры CRuntimeClass

Описание

const char* m_pszClassName

Указатель на строку, закрытую двоичным нулем, в которой расположено имя класса

int m_nObjectSize

Размер объектов класса

WORD m_wSchema

Номер схемы (schema number) класса. Используется при автоматическом сохранении и восстановлении объектов класса в файле. Если объекты класса не могут быть сохранены и восстановлены (в объявлении класса отсутствует макрокоманда IMPLEMENT_SERIAL), m_wSchema содержит значение -1

void (*m_pfnConstruct)
(void* p)

Указатель на конструктор класса, используемый по умолчанию. Этот конструктор не имеет параметров

CRuntimeClass* m_pBaseClass

Указатель на структуру CRuntimeClass, содержащую аналогичную информацию о базовом классе

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

CObject* CreateObject();

Метод IsKindOf

Метод IsKindOf XE "CObject:IsKindOf" определяет отношение объекта и класса, представленного указателем pClass на структуру CRuntimeClass. Метод правильно работает только для классов, в объявлении которых указаны макрокоманды DECLARE_DYNAMIC XE "DECLARE_DYNAMIC" или DECLARE_SERIAL XE "DECLARE_SERIAL" .

BOOL IsKindOf(const CRuntimeClass* pClass) const;

Метод возвращает ненулевое значение, если объект, для которого он вызван, принадлежит классу заданному параметром pClass или классу наследованному от него. В противном случае метод возвращает нулевое значение.

[Назад] [Содеожание] [Дальше]