Какая польза от CComPtr над CComQIPtr в COM? - PullRequest
18 голосов
/ 27 июля 2011

Может ли кто-нибудь объяснить, что такое использование CComPtr над CComQIPtr в COM?

CComPtr<ISampleInterface> Sample1;
CComQIPtr<ISampleInterface> Sample2;

Ответы [ 5 ]

26 голосов
/ 27 июля 2011

CComQIPtr - для случаев, когда вы хотите удобно позвонить на QueryInterface(), чтобы узнать, поддерживается ли интерфейс:

IInterface1* from = ...
CComQIPtr<IInterface2> to( from );
if( to != 0 ) {
   //supported - use
}

Таким образом, вы можете запросить интерфейс от указателя на любой(несвязанный) интерфейс COM и проверьте, успешно ли выполнен этот запрос.

CComPtr используется для управления объектами, которые наверняка поддерживают некоторый интерфейс.Вы используете его как обычный умный указатель с подсчетом ссылок.Это похоже на CComQIPtr, но не позволяет использовать описанный выше вариант использования, и это повышает безопасность типов.

Этот код:

IUnknown* unknown = ... ;
CComQIPtr<IDispatch> dispatch( unknown );

компилируется и, возможно, возвращает нулевой указатель, еслиunknown привязан к объекту, который не реализует IDispatch.Теперь вы должны проверить это во время выполнения, что хорошо, если вы хотите проверить во время выполнения, но плохо, если вы предпочитаете проверку типа времени компиляции.

Этот код:

IUnknown* unknown = ... ;
CComPtr<IDispatch> dispatch( unknown );

просто не скомпилируется - выдает

ошибка C2664: 'ATL :: CComPtr :: CComPtr (IDispatch *) throw ()': невозможно преобразовать параметр 1 из 'IUnknown *' в 'IDispatch * '

, что обеспечивает лучшую безопасность типов времени компиляции.

2 голосов
/ 27 июля 2011
template<class T,
   const IID* piid = &__uuidof(T)>
class CComQIPtr: public CComPtr<T>

Преобразователь выводит UUID данного типа автоматически через аргумент шаблона по умолчанию.

1 голос
/ 22 января 2015

Следующая статья MSDN объясняет разницу и рекомендует использовать CComPtr вместо CComQIPtr

Как: создавать и использовать экземпляры CComPtr и CComQIPtr

0 голосов
/ 15 июня 2015

"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.

0 голосов
/ 14 декабря 2011

Замечание к ответу о зуборезе.Просто попытался скомпилировать что-нибудь.как

CComQIPtr<IInterface2> to( from );

и не удалось.Задание вместо этого сработало:

CComQIPtr<IInterface2> to = from;

К сожалению, у меня нет времени, чтобы проанализировать это дальше ...

...