65.9K
CodeProject 正在变化。 阅读更多。
Home

COM 智能指针

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.18/5 (19投票s)

2001年10月15日

2分钟阅读

viewsIcon

203672

downloadIcon

1732

一个COM接口指针的包装类。

引言

CComPtr封装了任何接口指针,并且会正确地调用AddRef()Release()。也就是说,您无需担心控制接口指针的生命周期。

详细说明

  1. ATL确实提供了一个名为CComQIPtr的智能指针类。但是它使用了一些ATL相关的功能,因此只能在ATL环境中使用。
  2. VC确实提供了_com_ptr_t & _bstr_ptr_t关键字来提供某种包装。但是它依赖于MS VC编译器,如果没有它,您将无法受益。
  3. 我的CComPtr提供了与编译器无关的功能来包装除IUnknown之外的任何接口指针。稍后我将解释为什么会有这个限制。

图示

注意INTERFACEpiid通过模板参数传递到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对象。此运算符有三个不同的参数列表。
    1. 参数为INTERFACE*
    2. 参数是另一个CComPtr对象。
    3. 参数是指向IUnknown的接口指针,该指针将用于查询piid定义的其他接口指针。

CComPtr还有另外三个方法。

  • Attach : 用于将现有的接口指针附加到CComPtr对象。
  • Detach : 用于从CComPtr对象中分离接口指针。
  • Release : 用于显式释放包装的接口指针。

CComPtr是用纯C++实现的。也就是说,它不依赖于任何特定的C/C++编译器,并且可以在任何符合ANSI C/C++标准的编译器下编译。我已经在VC++ 6.0中进行了测试。我确信它在GNU C/C++和MAC CodeWarrior中也能工作。

© . All rights reserved.