Сущность технологии СОМ. Библиотека программиста | страница 59
// и должен быть обработан AddRef'ом ( принцип A2)
reinterpretcast
return SOK;
}
Использование staticcast более предпочтительно, чем традиционные приведения типа в стиле С:
*ppv = (IPug*)this;
так как вариант staticcast вызовет ошибку этапа компиляции, если произведенное приведение типа не согласуется с существующим базовым классом.
Заметим, что в показанной здесь реализации QueryInterface при запросе на интерфейс, поддерживающийся более чем одним базовым интерфейсом (например, IUnknown, IAnimal) приведение типа должно явно выбрать более определенный базовый класс. Например, для класса PugCat такой вполне безобидно выглядящий код не откомпилируется:
if (riid == IIDIUnknown) *ppv = staticcast
Этот код не пройдет компиляцию, поскольку такое приведение типа является неоднозначным и может соответствовать более чем одному базовому классу. Это было показано в случае FastString и IExtensibleObject из предыдущей главы. Вместо этого реализация должна более точно выбрать тип для приведения:
if (riid == IIDIUnknown) ppv = staticcast
или if (riid == IIDIUnknown) ppv = staticcast
Каждый из этих двух фрагментов кода допустим для реализации PugCat. Первый вариант предпочтительнее, так как многие компиляторы выдают несколько более эффективный код, когда использован крайний левый базовый класс[1].
Использование указателей интерфейса СОМ
Программисты C++ должны использовать методы IUnknown явно, потому что перевод модели СОМ на язык C++ не предусматривает использования среды поддержки выполнения (runtime layer) между кодом клиента и кодом объекта. Поэтому IUnknown можно рассматривать просто как набор обещаний, которые все программисты СОМ дают друг другу. Это дает преимущество программистам C++, так как C++ может создавать код, который потенциально более эффективен, чем языки, которые требуют такого динамического слоя при работе с СОМ.
При работе на Visual Basic и Java, в отличие от C++, программисты никогда не видят QueryInterface, AddRef или Release. Для этих двух языков детали IUnknown надежно скрыты за поддерживающей эти языки виртуальной машиной. На Java QueryInterface просто отображается в приведение типа:
public void TryToSnoreAndIgnore(Object obj)
{
IPug pug;
try
{
pug = (IPug)obj;
// VM calls QueryInterface
// VM вызывает QueryInterface
pug.Snore();
}
catch (Throwable ex)
{
// ignore method or QI failures
// игнорируем сбой метода или QI