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


Реализация IUnknown - часть 4


При наличии реализации AddRef и Release единственным еще не реализованным методом из IUnknown остается QueryInterface. Его реализации должны отслеживать иерархию типов объекта и использовать статические приведения типов для возврата правильного типа указателя для всех поддерживаемых интерфейсов. Для определения класса PugCat, рассмотренного ранее, следующий код является корректной реализацией QueryInterface:

STDMETHODIMP PugCat::QueryInterface(REFIID riid, void **ppv) { assert(ppv != 0); // or return E_POINTER in production // или возвращаем E_POINTER в реальный продукт if (riid == IID_IPug) *ppv = static_cast<IPug*>(this); else if (riid == IID_IDog) *ppv = static_cast<IDog*>(this); else if (riid == IID_IAnimal) // cat or pug? // кот или мопс? *ppv == static_cast<IDog*>(this); else if (riid == IID_IUnknown) // cat or pug? // кот или мопс? *ppv = static_cast<IDog*>(this); else if (riid == IID_ICat) *ppv = static_cast<ICat*>(this); else { // unsupported interface // неподдерживаемый интерфейс *ppv = 0; return E_NOINTERFACE; } // if we reach this point, *ppv is non-null // and must be AddRef'ed (guideline A2) // если мы дошли до этого места, то *ppv ненулевой // и должен быть обработан AddRef'ом ( принцип A2) reinterpret_cast<IUnknown*>(*ppv)->AddRef(); return S_OK; }

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

*ppv = (IPug*)this;

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

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

if (riid == IID_IUnknown) *ppv = static_cast<IUnknown*>(this);

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


Начало  Назад  Вперед