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

ОглавлениеДобавить в закладки К обложке

// tearoff exists, let tearoff QI

// отделяемый интерфейс существует, пусть это QI

return m_pTearOff->QueryInterface(riid, ppv);

else

// memory allocation failure

// ошибка выделения памяти

return (*ppv = 0), E_NOINTERFACE;

}

else …

:

:

:

}

На основе показанной здесь реализации QueryInterface на каждый объект будет приходиться по большей части по одному отделяемому интерфейсу. Это значит, что в случае отсутствия запросов на транспортные интерфейсы объект будет тратить в сумме 12 байт (vptr IUnknown + счетчик ссылок + кэшированный указатель на отделяемый интерфейс). Если транспортный интерфейс запрошен, то объект будет тратить в сумме от 24 до 28 байт (исходные 12 байт + наследующий Vehicle vptr + счетчик ссылок + обратный указатель на главный объект + (необязательно) служебная запись malloc (memory allocation – выделение памяти)).

Если бы в данном случае отделяемые интерфейсы не использовались, то определение класса выглядело бы примерно так:

class GenericVehicle : public ITruck, public IHelicopter, public IBoat, public ICar, public IMonsterTruck, public IBicycle, public IMotorcycle, public ICar, public IPlane, public ISkateboard { LONG m_cRef;

// IUnknown methods – методы IUnknown

:

:

:

};

В результате этот класс создал бы объекты, тратящие всегда 44 байта (десять vptr + счетчик ссылок). Хотя производящий класс может показаться немного запутанным, постоянные интерфейсы СОМ принадлежат к аналогичной категории, так как в настоящее время существует восемь различных постоянных интерфейсов, но объект обычно выставляет только один из них на экземпляр. В то же время разработчик класса не всегда может предсказать, какой из интерфейсов будет запрошен определенным клиентом (и будет ли какой-либо). Кроме того, каждый из восьми интерфейсов требует своего набора поддерживающих элементов данных для корректной реализации методов интерфейса. Если эти элементы данных были созданы как часть отделяемого интерфейса, а не главного объекта, то для каждого объекта будет назначен только один набор элементов данных. Этот тип сценария идеален для отделяемых интерфейсов, но опять же, для большей эффективности, указатель на отделяемый интерфейс следует кэшировать в главном объекте.


Логин
Пароль
Запомнить меня