【发布时间】:2011-10-14 06:26:57
【问题描述】:
谁能解释一下,COM 中 CComPtr 而不是 CComQIPtr 的用途是什么?
CComPtr<ISampleInterface> Sample1;
CComQIPtr<ISampleInterface> Sample2;
【问题讨论】:
标签: visual-c++ com atl smart-pointers
谁能解释一下,COM 中 CComPtr 而不是 CComQIPtr 的用途是什么?
CComPtr<ISampleInterface> Sample1;
CComQIPtr<ISampleInterface> Sample2;
【问题讨论】:
标签: visual-c++ com atl smart-pointers
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 *'
这提供了更好的编译时类型安全性。
【讨论】:
CComQIPtr 时,它可以尝试将任何类型指针绑定到任何类型对象,如果该接口不受支持,则会产生一个空指针,并且您必须在运行时检查它并为此提供额外的代码。跨度>
template<class T,
const IID* piid = &__uuidof(T)>
class CComQIPtr: public CComPtr<T>
Former 通过默认模板参数自动推断给定类型的 UUID。
【讨论】:
下面的 MSDN 文章解释了区别并建议使用 CComPtr 而不是 CComQIPtr
【讨论】:
QueryInterfaceing 推荐为CComPtr,在那里你会得到一个说明失败原因的HRESULT,而不是使用CComQIPtr,你总是得到nullptr,你不知道为什么(接口未实现?访问被拒绝?没有代理/存根?代理/存根未注册?代理/存根 dll 未找到?没有类型库?类型库未注册?类型库未找到?rpc 错误?没有更多内存?)跨度>
评论尖牙的答案。只是试图编译某事。喜欢
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 对应的接口指针。
【讨论】: