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" содержит различную информацию о классе. Ниже перечислены несколько основные полей этой структуры.
Кроме перечисленных элементов структуры, она содержит метод 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 или классу наследованному от него. В противном случае метод возвращает нулевое значение. |