Читаем Сущность технологии СОМ. Библиотека программиста полностью

Эта методика работает, поскольку транслятор имеет достаточно информации о представлении и иерархии типов класса реализации, чтобы динамически проверить объект для выяснения того, действительно ли он порожден от IPersistentObject. Но здесь есть одна проблема.

RTTI – особенность, сильно зависящая от транслятора. В свою очередь, DWP передает синтаксис и семантику RTTI, но каждая реализация RTTI разработчиком транслятора уникальна и запатентована. Это обстоятельство серьезно подрывает независимость от транслятора, которая была достигнута путем использования абстрактных базовых классов как интерфейсов. Это является неприемлемым для архитектуры компонентов, не зависимой от разработчиков. Удачным решением было бы упорядочение семантики dynamic_cast без использования свойств языка, зависящих от транслятора. Явное выставление хорошо известного метода из каждого интерфейса, представляющего семантический эквивалент dynamic_cast, позволяет достичь желаемого эффекта, не требуя, чтобы все объекты использовали тот же самый транслятор C++:

class IPersistentObject

{

public: virtual void *Dynamic_Cast(const char *pszType) = 0;

virtual void Delete(void) = 0;

virtual bool Load(const char *pszFileName) = 0;

virtual bool Save(const char *pszFileName) = 0;

};

class IFastString

{

public: virtual void *Dynamic_Cast(const char *pszType) = 0;

virtual void Delete(void) = 0;

virtual int Length(void) = 0;

virtual int Find(const char *psz) = 0;

};

Так как всем интерфейсам необходимо выставить этот метод вдобавок к уже имеющемуся методу Delete, имеет большой смысл включить общее подмножество методов в базовый интерфейс, из которого могли бы порождаться все последующие интерфейсы:

class IExtensibleObject { public: virtual void *Dynamic_Cast(const char* pszType) = 0; virtual void Delete(void) = 0; }; class IPersistentObject : public IExtensibleObject { public: virtual bool Load(const char *pszFileName) = 0; virtual bool Save(const char *pszFileName) = 0; }; class IFastString : public IExtensibleObject { public: virtual int Length(void) = 0; virtual int Find(const char *psz) = 0; };

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

bool SaveString(IFastString *pfs, const char *pszFN) { boot bResult = false; IPersistentObject *ppo = (IPersistentObject) pfs->Dynamic_Cast(«IPers1stentObject»); if (ppo) bResult = ppo->Save(pszFN); return bResult; }

В только что приведенном примере клиентского использования присутствуют требуемая семантика и механизм для определения типа, но каждый класс реализации должен выполнять это функциональное назначение самолично:

class FastString : public IFastString, public IPersistentObject

{

int m_cсh;

// count of characters

// счетчик символов

char *m_psz;

public:

FastString(const char *psz);

~FastString(void);

// IExtensibleObject methods

// методы IExtensibleObject

void *Dynamic_Cast(const char *pszType);

void Delete(void);

// deletes this instance

// удаляет этот экземпляр

// IFastString methods

// методы IFastString

int Length(void) const;

// returns # of characters

// возвращает число символов

int Find(const char *psz) const;

// returns offset

// возвращает смещение

// IPersistentObject methods

// методы IPersistentObject

bool Load(const char *pszFileName);

bool Save(const char *pszFileName);

};

Реализации Dynamic_Cast необходимо имитировать действия RTTI путем управления иерархией типов объекта. Рисунок 1.8 иллюстрирует иерархию типов для только что показанного класса FastString. Поскольку класс реализации порождается из каждого интерфейса, который он выставляет, реализация Dynamic_Cast в FastString может просто использовать явные статические приведения типа (explicit static casts), чтобы ограничить область действия указателя this, основанного на подтипе, который запрашивается клиентом:

void *FastString::Dynam1c_Cast(const char *pszType)

{

if (strcmp(pszType, «IFastString») == 0) return static_cast(this);

else if (strcmp(pszType, «IPersistentObject») == 0) return static_cast(this);

else if (strcmp(pszType, «IExtensibleObject») == 0) return static_cast(this);

else return 0;

// request for unsupported interface

// запрос на неподдерживаемый интерфейс

}

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

Отметим, что после запроса на общий базовый интерфейс IExtensibleObject реализация статически преобразуется в IFastString. Это происходит потому, что интуитивная версия (intuitive version) оператора

return static_cast(this);

Перейти на страницу:

Похожие книги

C++: базовый курс
C++: базовый курс

В этой книге описаны все основные средства языка С++ - от элементарных понятий до супервозможностей. После рассмотрения основ программирования на C++ (переменных, операторов, инструкций управления, функций, классов и объектов) читатель освоит такие более сложные средства языка, как механизм обработки исключительных ситуаций (исключений), шаблоны, пространства имен, динамическая идентификация типов, стандартная библиотека шаблонов (STL), а также познакомится с расширенным набором ключевых слов, используемым в .NET-программировании. Автор справочника - общепризнанный авторитет в области программирования на языках C и C++, Java и C# - включил в текст своей книги и советы программистам, которые позволят повысить эффективность их работы. Книга рассчитана на широкий круг читателей, желающих изучить язык программирования С++.

Герберт Шилдт

Программирование, программы, базы данных
Язык программирования Euphoria. Справочное руководство
Язык программирования Euphoria. Справочное руководство

Euphoria (юфо'ри, также рус. эйфори'я, ра'дость) — язык программирования, созданный Робертом Крейгом (Rapid Deployment Software) в Канаде, Торонто. Название Euphoria — это акроним для «End-User Programming with Hierarchical Objects for Robust Interpreted Applications».Euphoria — интерпретируемый императивный язык высокого уровня общего назначения. C помощью транслятора из исходного кода на Euphoria может быть сгенерирован исходный код на языке Си, который в свою очередь может быть скомпилирован в исполнияемый файл или динамическую библиотеку при помощи таких компиляторов, как GCC, OpenWatcom и др. Программа Euphoria также может быть «связана» с интерпретатором для получения самостоятельного исполняемого файла. Поддерживается несколько GUI-библиотек, включая Win32lib и оберток для wxWidgets, GTK+ и IUP. Euphoria имеет встроенную простую систему баз данных и обертки для работы с другими типам баз данных.[Материал из Википедии]

Коллектив авторов

Программирование, программы, базы данных