COM 智能指针






3.18/5 (19投票s)
2001年10月15日
2分钟阅读

203672

1732
一个COM接口指针的包装类。
引言
CComPtr
封装了任何接口指针,并且会正确地调用AddRef()
和Release()
。也就是说,您无需担心控制接口指针的生命周期。
详细说明
- ATL确实提供了一个名为
CComQIPtr
的智能指针类。但是它使用了一些ATL相关的功能,因此只能在ATL环境中使用。 - VC确实提供了
_com_ptr_t
&_bstr_ptr_t
关键字来提供某种包装。但是它依赖于MS VC编译器,如果没有它,您将无法受益。 - 我的
CComPtr
提供了与编译器无关的功能来包装除IUnknown
之外的任何接口指针。稍后我将解释为什么会有这个限制。
图示
注意:INTERFACE
和piid
通过模板参数传递到CComPtr
类中。
CComPtr
有四个构造函数来满足不同的需求。
CComPtr()
简单的构造函数,什么也不做。
CComPtr(INTERFACE* lPtr)
使用现有的接口指针构造一个新的
CComPtr
对象。之后,这个新的CComPtr
对象可以像接口指针本身一样使用。
CComPtr(IUnknown* pIUnknown, IID iid)
使用一个
IUnknown
指针和一个IID构造一个新的CComPtr
对象,该IID代表您感兴趣的接口。在内部,构造函数将调用pIUnknown->QueryInterface
来根据IID获取接口指针。
CComPtr(const CComPtr<INTERFACE, piid>& RefComPtr)
此构造函数将另一个现有的
CComPtr
对象作为参数。之后,克隆旧的CComPtr
对象。
CComPtr
有一个析构函数,它会释放接口指针。
~CComPtr(){ if (m_Ptr) { m_Ptr->Release(); m_Ptr = NULL; } }
CComPtr
有五个运算符。
- (a) 运算符
INTERFACE*
: 返回由CComPtr
类包装的接口指针。
示例
CComPtr<IWavePciStream> m_wavePciStreamPtr; IWavePciStream* pWavePciStream = (IWavePciStream*)m_wavePciStreamPtr;
- (b) 运算符
*
: 用于获取由CComPtr
类包装的接口对象。
示例
CComPtr<IWavePciStream> m_wavePciStreamPtr; IWavePciStream wavePciStream = *m_wavePciStreamPtr;
- (c) 运算符
&
: 用于获取指向由CComPtr
类包装的接口指针的指针。
示例
CComPtr<IWavePciStream> m_wavePciStreamPtr; IWavePciStream** ppWavePciStream = &m_wavePciStreamPtr;
- (d) 运算符
->
: 用于使CComPtr
对象像一个TRUE
接口指针一样工作。
示例
CComPtr<IWavePciStream> m_wavePciStreamPtr; m_wavePciStreamPtr->AnyPciStreamMethods();
- (e) 运算符
=
: 用于将现有的接口指针信息传输到新的CComPtr
对象。此运算符有三个不同的参数列表。- 参数为
INTERFACE*
- 参数是另一个
CComPtr
对象。 - 参数是指向
IUnknown
的接口指针,该指针将用于查询piid定义的其他接口指针。
- 参数为
CComPtr
还有另外三个方法。
Attach
: 用于将现有的接口指针附加到CComPtr
对象。Detach
: 用于从CComPtr
对象中分离接口指针。Release
: 用于显式释放包装的接口指针。
CComPtr
是用纯C++实现的。也就是说,它不依赖于任何特定的C/C++编译器,并且可以在任何符合ANSI C/C++标准的编译器下编译。我已经在VC++ 6.0中进行了测试。我确信它在GNU C/C++和MAC CodeWarrior中也能工作。