Ramesh
Ramesh

Reputation: 267

What is the use of CComPtr over CComQIPtr in COM?

Can any one explain, What is the use of CComPtr over CComQIPtr in COM?

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

Upvotes: 22

Views: 13178

Answers (5)

sharptooth
sharptooth

Reputation: 170489

CComQIPtr is for cases when you want to call QueryInterface() in a convenient manner to know whether an interface is supported:

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

This way you can request an interface from a pointer to any (unrelated) COM interface and check whether that request succeeded.

CComPtr is used for managing objects that surely support some interface. You use it as a usual smart pointer with reference counting. It is like CComQIPtr, but doesn't allow the usecase described above and this gives you better type safety.

This code:

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

compiles and maybe yields a null pointer if unknown is bound to an object that doesn't implement IDispatch. You now have to check for that in runtime which is good if you wanted a runtime check in the first place but bad if you'd prefer a compile time type check.

This code:

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

will simply not compile - it yields

error C2664: 'ATL::CComPtr::CComPtr(IDispatch *) throw()' : cannot convert parameter 1 from 'IUnknown *' to 'IDispatch *'

which provides for better compile time type safety.

Upvotes: 32

kevinLi
kevinLi

Reputation: 11

"ATL uses CComQIPtr and CComPtr to manage COM interface pointers. Both classes perform automatic reference counting through calls to AddRef and Release. Overloaded operators handle pointer operations. CComQIPtr additionally supports automatic querying of interfaces though QueryInterface."

And where do you use one over the other?

When you do not want to call 'QueryInterface()' 'manually', use 'CComQIPtr':

CComQIPtr( T* lp );

CComQIPtr( const CComQIPtr< T, piid >& lp );

If you pass a pointer type derived from T, the constructor sets p to the T* parameter and calls AddRef. If you pass a pointer type not derived from T, the constructor calls QueryInterface to set p to an interface pointer corresponding to piid.

Upvotes: 0

vikas pachisia
vikas pachisia

Reputation: 615

The following MSDN article explains the difference and recommends using CComPtr instead of CComQIPtr

How to: Create and Use CComPtr and CComQIPtr Instances

Upvotes: 1

yau
yau

Reputation: 555

Remark on the answer of sharptooth. Just tried to compile sth. like

CComQIPtr<IInterface2> to( from );

and failed. Assignment instead worked:

CComQIPtr<IInterface2> to = from;

Unfortunately I have no time to analyse this further...

Upvotes: 0

Ajay
Ajay

Reputation: 18431

template<class T,
   const IID* piid = &__uuidof(T)>
class CComQIPtr: public CComPtr<T>

Former deduces the UUID of given type automatically, via default template argument.

Upvotes: 2

Related Questions