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



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


class IExtensibleObject

{

public:

virtual void *DynamicCast (const char* pszType) =0;

virtual void Delete(void) = 0;

};


на


class IExtensibleObject

{

public:

virtual void *DynamicCast(const char* pszType) = 0;

virtual void DuplicatePointer(void) = 0;

virtual void DestroyPointer(void) = 0;

};


Разместив эти методы, все пользователи IExtensibleObject должны теперь придерживаться следующих двух соображений:

1) Когда указатель интерфейса дублируется, требуется вызов DuplicatePointer.

2) Когда указатель интерфейса более не используется, следует вызвать DestroyPointer.

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


class FastString : public IFastString,

public IPersistentObject

{

int mcPtrs;

// count of outstanding ptrs

// счетчик невыполненных указателей

public:

// initialize pointer count to zero

// сбросить счетчик указателя в нуль

FastString(const char *psz) : mcPtrs(0) { }

void DuplicatePointer(void)

{

// note duplication of pointer

// отметить дублирование указателя

++mcPtrs;

}

void DestroyPointer(void)

{

// destroy object when last pointer destroyed

// уничтожить объект, когда уничтожен последний указатель

if (-mcPtrs == 0) delete this;

}

: : :

};


Этот совершенно стандартный код мог бы просто быть включен в базовый класс или в макрос С-препроцессора, чтобы его могли использовать все реализации.

Чтобы поддерживать эти методы, все программы, которые манипулируют или управляют указателями интерфейса, должны придерживаться двух простых правил DuplicatePointer/DestroyPointer. Для реализации FastString это означает модификацию двух функций. Функция CreateFastString берет начальный указатель, возвращаемый новым оператором C++, и копирует его в стек для возврата клиенту. Следовательно, необходим вызов DuplicatePointer:


IFastString* CreateFastString(const char *psz)

{

IFastString *pfsResult = new FastString(psz);

if (pfsResult) pfsResult->DuplicatePointer();

return pfsResult;

}


Реализация копирует указатель и в другом месте – в методе Dynamic_Cast:


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

{

void *pvResult = 0;

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