Алекс Jenter - Программирование на Visual C++. Архив рассылки

Тут можно читать онлайн Алекс Jenter - Программирование на Visual C++. Архив рассылки - бесплатно полную версию книги (целиком) без сокращений. Жанр: comp-programming. Здесь Вы можете читать полную версию (весь текст) онлайн без регистрации и SMS на сайте лучшей интернет библиотеки ЛибКинг или прочесть краткое содержание (суть), предисловие и аннотацию. Так же сможете купить и скачать торрент в электронном формате fb2, найти и слушать аудиокнигу на русском языке или узнать сколько частей в серии и всего страниц в публикации. Читателям доступно смотреть обложку, картинки, описание и отзывы (комментарии) о произведении.
  • Название:
    Программирование на Visual C++. Архив рассылки
  • Автор:
  • Жанр:
  • Издательство:
    неизвестно
  • Год:
    неизвестен
  • ISBN:
    нет данных
  • Рейтинг:
    4.33/5. Голосов: 91
  • Избранное:
    Добавить в избранное
  • Отзывы:
  • Ваша оценка:
    • 80
    • 1
    • 2
    • 3
    • 4
    • 5

Алекс Jenter - Программирование на Visual C++. Архив рассылки краткое содержание

Программирование на Visual C++. Архив рассылки - описание и краткое содержание, автор Алекс Jenter, читайте бесплатно онлайн на сайте электронной библиотеки LibKing.Ru

РАССЫЛКА ЯВЛЯЕТСЯ ЧАСТЬЮ ПРОЕКТА RSDN, НА САЙТЕ КОТОРОГО ВСЕГДА МОЖНО НАЙТИ ВСЮ НЕОБХОДИМУЮ РАЗРАБОТЧИКУ ИНФОРМАЦИЮ, СТАТЬИ, ФОРУМЫ, РЕСУРСЫ, ПОЛНЫЙ АРХИВ ПРЕДЫДУЩИХ ВЫПУСКОВ РАССЫЛКИ И МНОГОЕ ДРУГОЕ.

Программирование на Visual C++. Архив рассылки - читать онлайн бесплатно полную версию (весь текст целиком)

Программирование на Visual C++. Архив рассылки - читать книгу онлайн бесплатно, автор Алекс Jenter
Тёмная тема
Сбросить

Интервал:

Закладка:

Сделать
Реестр типов

Чтобы осуществить идентификацию объектов во время выполнения, MFC создает в приложении реестр классов, унаследованных от CObject . Этот реестр никак не связан с OLE-реестром, но их концепции схожи. Реестр типов представляет собой связанный список структур CRuntimeClass , в котором каждая структура описывает один класс-наследник CObject . На листинге 1 показано внутреннее устройство структуры CRuntimeClass .

Листинг 1

struct CRuntimeClass {

// Attributes

LPCSTR m_lpszClassName;

int m_nObjectSize;

UINT m_wSchema; // номер схемы загруженного класса

void (PASCAL* m_pfnConstruct)(void* p); // NULL => abstract class

CRuntimeClass* m_pBaseClass;

// Operations

CObject* CreateObject();

// Implementation

BOOL ConstructObject(void* pThis);

void Store(CArchive& ar);

static CRuntimeClass* PASCAL Load(CArchive& ar, UINT* pwSchemaNum);

// объекты CRuntimeClass, связанные в простой список

CRuntimeClass* m_pNextClass;// список зарегистрированных классов

};

Весь фокус в том, что типы из этого реестра не прописаны ни в одной таблице. Первый ключ к разгадке этого феномена находится в начале файла SCRIBDOC.H из MFC-примера "Scribble". Начало объявления класса выглядит так, как показано в примере 1(a).

Пример 1: (a) Начало объявления класса; (b) после обработки препроцессором макрос DECLARE_DYNCREATE разворачивается в несколько новых членов класса.

(a)

class CScribDoc : public CDocument {

protected:

// создавать только при сериализации

CScribDoc();

DECLARE_DYNCREATE(CScribDoc)

...

};

(b)

protected:

static CRuntimeClass* __stdcall _GetBaseClass();

public:

static CRuntimeClass classCScribDoc;

virtual CRuntimeClass* GetRuntimeClass() const;

static void__stdcall Construct(void* p);

В документации сказано, что макрос DECLARE_DYNCREATE позволяет классам-наследникам CObject создаваться динамически во время выполнения. Хотя это определение абсолютно верно, то, что происходит внутри этого макроса, гораздо интереснее. После обработки препроцессором макрос DECLARE_DYNCREATE разворачивается в несколько новых членов класса, как показано в примере 1(b) (Все примеры взяты из MFC 3.1 и Visual C++ 2.1. Я выровнял код, сгенерированный препроцессором, для повышения читабельности).

Идентификация типов времени выполнения в MFC базируется на виртуальной функции GetRuntimeClass() . Информация о типе доступна для любого объекта — потомка CObject , который включает в себя макросы DECLARE_DYNAMIC, DECLARE_DYNCREATE, или DECLARE_SERIAL. Эта информация позволяет Вам определить, может ли объект быть приведен к типу унаследованного класса или принадлежат ли два объекта одному и тому же классу. Хотя Visual C++ и не поддерживает новый C++-оператор dynamic_cast [ помним, что речь идет о Visual C++ 2.1 - прим.пер. ], использование вышеописанной информации о типе времени выполнения даст тот же эффект.

Информация о типе времени выполнения объявляется при помощи статической переменной класса, в данном случае classCScribDoc . Это имя (без пробела внутри) создается в макросах DECLARE_xxx через оператор макро-конкатенации. Для доступа к этой переменной используются функции класса _GetBaseClass() и GetRuntimeClass() . GetRuntimeClass() является виртуальной, поэтому тип объекта может быть определен даже через указатель на CObject .

И наконец, статическая функция класса Construct() образует базис для использования реестра классов MFC как фабрики классов, которая может, когда требуется, создавать объекты произвольных типов. Для понимания работы Construct() необходимы дополнительные разьяснения.

Создание объекта

В книге Advanced C++: Programming Styles and Idioms (Addison-Wesley, 1992), Джеймс O. Коплин так описывает концепцию виртуального конструктора:

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

В MFC контекстом является информация, прочитанная из упорядоченного (serialized) архива [ под архивом в этой статье понимается хранилище данных – прим.пер. ]. Однако, виртуальный конструктор – это лишь концепция; никакая конструкция языка не реализует ее напрямую. Оператор new требует явного указания типа. Виртуальные конструкторы могут быть реализованы, если ввести в каждый класс статическую функцию, которая будет вызывать new для этого класса. Эта статическая функция-член будет вызываться при создании объекта определенного типа.

В MFC эта функция-член называется Construct() . Она создается макросами IMPLEMENT_DYNCREATE или IMPLEMENT_SERIAL. Один из этих макросов обязательно должен появиться в .cpp-модуле ровно один раз для каждого класса с поддержкой динамического создания. В случае со Scribble, выражение IMPLEMENT_DYNCREATE(CScribDoc, CDocument) появляется почти в самом начале файла SCRIBDOC.CPP. Первым аргументом идет класс, а вторым – его класс-родитель. Листинг 2 показывает код, сгенерированный препроцессором.

Когда MFC нужен документ или любой другой объект класса, унаследованного от CObject , она вызывает функцию CreateObject() класса CRuntimeClass. CreateObject() выделяет память, используя размер, указанный в структуре CRuntimeClass , и после этого вызывает ConstructObject(). ConstructObject() проверяет, поддерживает ли класс динамическое конструирование и вызывает функцию Construct() создаваемого класса.

Хотя в исходных текстах не дается пояснений, ясно, что такая схема четко разделяет конструирование объекта и выделение памяти. Все это кажется лишним, но в определенных ситуациях без такой организации не обойтись. Например, чтобы при создании массива его элементы располагались в одном блоке памяти, эту память нужно выделять одним вызовом функции malloc() . Используя ConstructObject() , Вы можете вручную инициализировать каждый элемент. Такой механизм позволяет принимать на этапе выполнения решения, которые в C++ обычно принимаются на этапе компиляции.

В примере 2 показана функция Construct() . Синтаксис вызова new немного необычен. На самом деле вызывается функция CObject::operator new(size_t, void*) . Помните, что размер структуры — это подразумеваемый аргумент при вызове new , однако его следует явно описать в определении оператора. Эта версия new в CObject ничего не делает, но вызов new дает побочным эффектом вызов конструктора для этого объекта. Память уже была выделена вызовом CreateObject с использованием информации о размере из CRuntimeClass .

Пример 2: Функция Construct().

void __stdcall CScribDoc::Construct(void* p) {

new(p) CScribDoc;

}

Используя реестр классов CRuntimeClass и функцию-член Construct() , MFC удается находить и создавать объекты новых типов на лету, что решает Проблему 1. Потенциально серьезные последствия данной техники в том, что при этом не поддерживаются множественное наследование и виртуальные базовые классы (см. MFC Technical Note #16).

Читать дальше
Тёмная тема
Сбросить

Интервал:

Закладка:

Сделать


Алекс Jenter читать все книги автора по порядку

Алекс Jenter - все книги автора в одном месте читать по порядку полные версии на сайте онлайн библиотеки LibKing.




Программирование на Visual C++. Архив рассылки отзывы


Отзывы читателей о книге Программирование на Visual C++. Архив рассылки, автор: Алекс Jenter. Читайте комментарии и мнения людей о произведении.


Понравилась книга? Поделитесь впечатлениями - оставьте Ваш отзыв или расскажите друзьям

Напишите свой комментарий
x