Сущность технологии COM


Абстрактные базы как двоичные интерфейсы - часть 5


Поскольку классу FastString можно приписывать различные конкретные типы данных, его таблица vtbl будет содержать указатели на существующие реализации методов Length и Find. Их связь показана на рис. 1.6.

Даже несмотря на то, что открытые операторы над типами данных подняты до уровня чисто виртуальных функций в классе интерфейса, клиент не может приписывать значения объектам FastString, не имея определения класса для класса реализации. При демонстрации клиенту определения класса реализации от него будет скрыта двоичная инкапсуляция интерфейса; что не позволит клиенту использовать класс интерфейса. Одним из разумных способов обеспечить клиенту возможность использовать объекты FastString является экспорт из DLL глобальной функции, которая будет вызывать новый оператор от имени клиента. При условии, что эта подпрограмма экспортируется с опцией extern "С", она будет доступна для любого транслятора C++.

Рис. 1.6. Двоичное представление классов интерфейс/реализация

// ifaststring.h class IFastString { public: virtual int Length(void) const = 0; virtual int Find(const char *psz) const = 0; };

extern "C" IFastString *CreateFastString(const char *psz); // faststring.cpp (part of DLL) // faststring.cpp (часть DLL) IFastString *CreateFastString (const char *psz) { return new FastString(psz); }

Как было в случае класса-дескриптора, новый оператор вызывается исключительно внутри DLL FastString, а это означает, что размер и расположение объекта будут установлены с использованием того же транслятора, который транслировал все методы реализации.

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

int f(void) { IFastString *pfs = CreateFastString("Deface me"); int n = pfs->Find("ace me"); delete pfs; return n; }

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


Начало  Назад  Вперед



Книжный магазин