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



Двоичная композиция - часть 5


Имея прототип функции, приведенный выше, класс CarBoat после небольшой модификации будет удовлетворять правилам агрегации:

CarBoat::CarBoat(void) : m_cRef(0) { // need to pass identity of self to Create routine // to notify car object it 1s an aggregate // нужно передать свою идентификацию подпрограмме // Create для уведомления объекта car, что он - агрегат HRESULT hr = CoCreateInstance(CLSID_Car, this, CLSCTX_ALL, IID_IUnknown, (void**)&m_pUnkCar); assert(SUCCEEDED(hr)); }

Реализация CarBoat QueryInterface просто переадресовывает запрос ICar внутреннему агрегату:

STDMETHODIMP CarBoat::QueryInterface(REFIID riid, void **ppv) { if (riid == IID_IUnknown) *ppv = static_cast<IUnknown*>(this); else if (riid == IID_ICar) // forward request... // переадресовываем запрос... return m_pUnkCar->QueryInterface(riid, ppv); else if (riid == IID_IBoat) : : :

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

В предыдущем сценарии метод CreateInstance класса Car возвращает внешнему объекту указатель интерфейса, наследующего IUnknown. Если бы этот интерфейсный указатель должен был просто делегировать вызовы функций интерфейсу IUnknown внешнего объекта, то невозможно было бы: 1) уведомить агрегат, что он больше не нужен; 2) запросить интерфейсные указатели при выделении их клиентам главного объекта. На деле результатом приведенной выше реализации QueryInterface будет бесконечный цикл, поскольку внешний объект делегирует функции внутреннему, который делегирует их обратно внешнему.

Для решения этой проблемы необходимо сделать так, чтобы начальный интерфейсный указатель, который возвращается внешнему объекту, не делегировал вызовы реализации IUnknown внешнего объекта. Это означает, что объекты, поддерживающие СОМ- агрегирование, должны иметь две реализации IUnknown. Делегирующая, то есть передающая функции, реализация переадресовывает все запросы QueryInterface, AddRef и Release внешней реализации.


Содержание  Назад  Вперед