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

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

PugCat::QueryInterface(REFIID riid, void **ppv)

{

assert(ppv != 0);

// or return EPOINTER in production

// или возвращаем EPOINTER в реальный продукт

if (riid == IIDIPug) *ppv = staticcast<IPug*>(this);

else if (riid == IIDIDog) *ppv = staticcast<IDog*>(this);

else if (riid == IIDIAnimal)

// cat or pug?

// кот или мопс?

*ppv == staticcast<IDog*>(this);

else if (riid == IIDIUnknown)

// cat or pug?

// кот или мопс?

*ppv = staticcast<IDog*>(this);

else if (riid == IIDICat) *ppv = staticcast<ICat*>(this);

else

{

// unsupported interface

// неподдерживаемый интерфейс

*ppv = 0;

return ENOINTERFACE;

}

// if we reach this point, *ppv is non-null

// and must be AddRef'ed (guideline A2)

// если мы дошли до этого места, то *ppv ненулевой

// и должен быть обработан AddRef'ом ( принцип A2)

reinterpretcast<IUnknown*>(*ppv)->AddRef();

return SOK;

}

Использование staticcast более предпочтительно, чем традиционные приведения типа в стиле С:

*ppv = (IPug*)this;

так как вариант staticcast вызовет ошибку этапа компиляции, если произведенное приведение типа не согласуется с существующим базовым классом.

Заметим, что в показанной здесь реализации QueryInterface при запросе на интерфейс, поддерживающийся более чем одним базовым интерфейсом (например, IUnknown, IAnimal) приведение типа должно явно выбрать более определенный базовый класс. Например, для класса PugCat такой вполне безобидно выглядящий код не откомпилируется:

if (riid == IIDIUnknown) *ppv = staticcast<IUnknown*>(this);

Этот код не пройдет компиляцию, поскольку такое приведение типа является неоднозначным и может соответствовать более чем одному базовому классу. Это было показано в случае FastString и IExtensibleObject из предыдущей главы. Вместо этого реализация должна более точно выбрать тип для приведения:

if (riid == IIDIUnknown) ppv = staticcast<IDog*>(this);

или if (riid == IIDIUnknown) ppv = staticcast<ICat*>(this);

Каждый из этих двух фрагментов кода допустим для реализации PugCat. Первый вариант предпочтительнее, так как многие компиляторы выдают несколько более эффективный код, когда использован крайний левый базовый класс[1].


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