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


Приведение типов и IUnknown - часть 3


Правильный вариант этого кода такой:

cleanup: if (pCat) pCat->Release(); // use AddRefed ptr // используем указатель AddRef if (pPug) pPug->Release(); // use AddRefed ptr // используем указатель AddRef

Здесь Release вызывается для того же интерфейсного указателя, для которого и AddRef (что произошло неявно, когда указатель был возвращен из QueryInterface). Это требование предоставляет разработчику значительную гибкость при реализации объекта. Например, объект может решить подсчитывать ссылки на каждый интерфейс, чтобы активным образом использовать ресурсы, которые обычно используются одним определенным интерфейсом на объект.

Еще одна тонкость относится ко второму параметру QueryInterface, имеющему тип void**. Весьма забавно то, что QueryInterface, являющийся основой системы типов СОМ, имеет довольно сомнительный в смысле типа аналог в C++:

HRESULT _stdcall QueryInterface(REFIID riid, void** ppv);

Как было отмечено ранее, клиенты вызывают QueryInterface, передавая объекту указатель на интерфейсный указатель в качестве второго параметра вместе с IID, который определяет тип ожидаемого интерфейсного указателя:

IPug *pPug = 0; hr = punk->QueryInterface(IID_IPug, (void**)&pPug);

К сожалению, для компилятора C++ таким же правильным выглядит и следующее:

IPug *pPug = 0; hr = punk->QueryInterface(IID_ICat, (void**)&pPug);

Даже еще более хитроумный вариант компилируется без ошибок:

IPug *pPug = 0; hr = punk->QueryInterface(IID_IPug, (void**)pPug);

Исходя из того, что правила наследования неприменимы к указателям, такое альтернативное определение QueryInterface нe облегчает проблему:

HRESULT QueryInterface(REFIID riid, IUnknown** ppv);

так как неявное приведение типа к родительскому типу (upcasting) применимо только к объектам и указателям на объекты, а не к указателям на указатели на объекты:

IDerived **ppd; IBase **ppb = ppd; // illegal // неверно

To же ограничение применимо в равной мере и к ссылкам на указатели. Следующее альтернативное определение вряд ли более удобно для использования клиентами:




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