Дональд Бокс - Сущность технологии СОМ. Библиотека программиста стр 19.

Книгу можно купить на ЛитРес.
Всего за 24.5 руб. Купить полную версию
Шрифт
Фон

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

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

// 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); }

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

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

int f(void)

{

IFastString *pfs = CreateFastString(«Deface me»);

int n = pfs-> Find(«ace me»);

delete pfs;

return n;

}

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

Очевидное решение этой проблемы – сделать деструктор виртуальным в классе интерфейса. К сожалению, это нарушит независимость класса интерфейса от транслятора, так как положение виртуального деструктора в таблицеvtbl может изменяться от транслятора к транслятору. Одним из конструктивных решений этой проблемы является добавление к интерфейсу явного методаDelete как еще одной чисто виртуальной функции, чтобы заставить производный класс уничтожать самого себя в своей реализации этого метода. В результате этого будет выполнен нужный деструктор. Модифицированная версия заголовочного файла интерфейса выглядит так:

// ifaststring.h

class IFastString

{

public:

virtual void Delete(void) = 0;

virtual int Length(void) const = 0;

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

};

extern "C"

IFastString *CreateFastString (const char *psz);

она влечет за собой соответствующее определение класса реализации:

// faststring.h

#include «ifaststring.h»

class FastString : public IFastString

{ const int mcch;

// count of characters

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

char *mpsz; public: FastString(const char *psz);

~FastString(void);

void Delete(void);

// deletes this instance

// уничтожает этот экземпляр

int Length(void) const;

// returns # of characters

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

int Find(const char *psz) const;

// returns offset

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

};

// faststring.cpp

#include

return new FastString(psz);

}

FastString::FastString(const char *psz) :mcch(strlen(psz)) ,mpsz(new char[m cch + 1]) {

strcpy( mpsz , psz);

}

void FastString::Delete(void) {

delete this;

}

FastString::~FastString(void) {

delete[]mpsz;

}

int FastString::Lengtn(void) const {

returnmcch;

}

int FastString::Find(const char *psz) const {

// O(1) lookup code deleted for clarity

// код поиска 0(1) уничтожен для ясности

}

Рисунок 1.7 показывает представлениеFastString на этапе выполнения.

Ваша оценка очень важна

0
Шрифт
Фон

Помогите Вашим друзьям узнать о библиотеке

Скачать книгу

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

fb2.zip txt txt.zip rtf.zip a4.pdf a6.pdf mobi.prc epub