Может ли кто-нибудь объяснить, что такое использование CComPtr над CComQIPtr в COM?
CComPtr<ISampleInterface> Sample1;
CComQIPtr<ISampleInterface> Sample2;
Может ли кто-нибудь объяснить, что такое использование CComPtr над CComQIPtr в COM?
CComPtr<ISampleInterface> Sample1;
CComQIPtr<ISampleInterface> Sample2;
CComQIPtr
предназначен для случаев, когда вы хотите вызвать QueryInterface()
удобным образом, чтобы узнать, поддерживается ли интерфейс:
IInterface1* from = ...
CComQIPtr<IInterface2> to( from );
if( to != 0 ) {
//supported - use
}
Таким образом вы можете запросить интерфейс от указателя на любой (несвязанный) COM-интерфейс и проверить, удалось ли выполнить этот запрос.
CComPtr
используется для управления объектами, которые, безусловно, поддерживают некоторый интерфейс. Вы используете его как обычный интеллектуальный указатель с подсчетом ссылок. Это похоже на CComQIPtr
, но не позволяет описанную выше процедуру usecase, и это дает вам лучшую безопасность типов.
Этот код:
IUnknown* unknown = ... ;
CComQIPtr<IDispatch> dispatch( unknown );
компилирует и, возможно, дает нулевой указатель, если unknown
связан с объектом, который не реализует IDispatch
. Теперь вам нужно проверить это во время выполнения, что хорошо, если вы хотите проверить время выполнения, но это плохо, если вы предпочитаете проверку типа времени компиляции.
Этот код:
IUnknown* unknown = ... ;
CComPtr<IDispatch> dispatch( unknown );
будет просто не компилироваться - это дает
ошибка C2664: 'ATL :: CComPtr :: CComPtr (IDispatch *) throw()': не может преобразовать параметр 1 из 'IUnknown *' в 'IDispatch *'
который обеспечивает лучшую безопасность времени компиляции.
template<class T,
const IID* piid = &__uuidof(T)>
class CComQIPtr: public CComPtr<T>
Бывший автоматически выводит UUID данного типа, используя аргумент шаблона по умолчанию.
Следующая статья MSDN объясняет разницу и рекомендует использовать CComPtr вместо CComQIPtr
Практическое руководство. Создание и использование экземпляров CComPtr и CComQIPtr
Замечание о ответе sharptooth. Просто попытался скомпилировать sth. как
CComQIPtr<IInterface2> to( from );
и потерпел неудачу. Присвоение вместо этого было выполнено:
CComQIPtr<IInterface2> to = from;
К сожалению, у меня нет времени анализировать это дальше...
"ATL использует CComQIPtr и CComPtr для управления указателями интерфейса COM. Оба класса выполняют автоматический подсчет ссылок через вызовы AddRef и Release. Перегруженные операторы обрабатывают операции указателя. CComQIPtr дополнительно поддерживает автоматический запрос интерфейсов, хотя QueryInterface."
И где вы используете один над другим?
Если вы не хотите называть 'QueryInterface()' 'вручную', используйте 'CComQIPtr':
CComQIPtr( T* lp );
CComQIPtr( const CComQIPtr< T, piid >& lp );
Если вы передаете тип указателя, полученный из T, конструктор устанавливает p в параметр T * и вызывает AddRef. Если вы передаете тип указателя, не полученный из T, конструктор вызывает QueryInterface для установки p на указатель интерфейса, соответствующий piid.