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中也能工作。
