метода 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 <string.h>

#include «faststring.h»

IFastString* CreateFastString (const char *psz) {

return new FastString(psz);

}

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

strcpy(mpsz, psz);

}

void FastString::Delete(void) {

delete this;

}

FastString::~FastString(void) {

delete[] mpsz;

}

int FastString::Lengtn(void) const {

return mcch;

}

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

// O(1) lookup code deleted for clarity

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

}

Рисунок 1.7 показывает представление FastString на этапе выполнения. Чтобы использовать тип данных FastString, клиентам надо просто включить в программу файл определения интерфейса и вызвать CreateFastString:

#include «ifaststring.h»

int f(void)

{ int n = -1;

IFastString *pfs = CreateFastString(«Hi Bob!»);

if (pfs) { n = pfs->Find(«ob»);

pfs->Delete(); }

return n; }

Отметим, что все, кроме одной, точки входа в DLL FastString являются виртуальными функциями. Виртуальные функции класса интерфейса всегда вызываются косвенно, через указатель функции, хранящийся в таблице vtbl , избавляя клиента от необходимости указывать их символические имена на этапе разработки. Это означает, что методы интерфейса защищены от различий в коррекции символических имен на разных трансляторах. Единственная точка входа, которая явно компонуется по имени, – это CreateFastString – глобальная функция, которая обеспечивает клиенту доступ в мир FastString. Заметим, однако, что эта функция была экспортирована с опцией extern 'С', которая подавляет коррекцию символов. Следовательно, все трансляторы C++ ожидают, что импортируемая библиотека и DLL экспортируют один и тот же идентификатор. Полезным результатом этой методики является то, что вы можете спокойно извлечь класс из DLL, использующей одну среду C++, а обратиться к этому классу из любой другой среды C++. Эта возможность необходима при построении основы для независимых от разработчика компонентов повторного пользования.

Полиморфизм на этапе выполнения

Управление реализациями классов с использованием абстрактных базовых классов как интерфейсов открывает целый мир новых возможностей в терминах того, что может случиться на этапе выполнения. Напомним, что DLL FastString экспортирует только один идентификатор – CreateFastString. Теперь пользователю легко динамически загрузить DLL, используя по требованию LoadLibrary, и разрешить этой единственной точке входа использовать GetProcAddress:

IFastString *CallCreateFastString(const char *psz)

Добавить отзыв
ВСЕ ОТЗЫВЫ О КНИГЕ В ИЗБРАННОЕ

0

Вы можете отметить интересные вам фрагменты текста, которые будут доступны по уникальной ссылке в адресной строке браузера.

Отметить Добавить цитату