有人能解释一下,CComPtr在COM中的作用是什么,与CComQIPtr相比有何优劣之处?
CComPtr<ISampleInterface> Sample1;
CComQIPtr<ISampleInterface> Sample2;
有人能解释一下,CComPtr在COM中的作用是什么,与CComQIPtr相比有何优劣之处?
CComPtr<ISampleInterface> Sample1;
CComQIPtr<ISampleInterface> Sample2;
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 );
无法编译 - 它会产生错误:
error C2664:'ATL :: CComPtr :: CComPtr(IDispatch *)throw()':无法将参数1从'IUnknown *'转换为'IDispatch *'
这提供了更好的编译时类型安全性。
template<class T,
const IID* piid = &__uuidof(T)>
class CComQIPtr: public CComPtr<T>
默认模板参数会自动推断给定类型的UUID。
QueryInterface
进入CComPtr
,在其中获取一个HRESULT来说明失败的原因,而不是使用CComQIPtr
,在其中你总是会得到nullptr
,并且你不知道为什么(接口未实现?访问被拒绝?没有代理/存根?代理/存根未注册?代理/存根DLL未找到?没有类型库?类型库未注册?类型库未找到?RPC错误?没有更多内存?) - acelentCComQIPtr( T* lp );
CComQIPtr( const CComQIPtr< T, piid >& lp );
如果您传递的是从 T 派生的指针类型,则构造函数将 p 设置为 T* 参数并调用 AddRef。如果您传递的是不从 T 派生的指针类型,则构造函数将调用 QueryInterface 来将 p 设置为与 piid 相应的接口指针。
关于sharptooth的回答,我刚试着编译了一些类似的东西。
CComQIPtr<IInterface2> to( from );
失败了。改为赋值就可以了:
CComQIPtr<IInterface2> to = from;
很遗憾我没有时间进一步分析这个问题...
CComQIPtr
时,它可以尝试将任何类型指针绑定到任何类型对象,如果接口不受支持,则会生成一个空指针,你将需要在运行时检查并编写额外的代码来处理该情况。 - sharptooth