码迷,mamicode.com
首页 > 其他好文 > 详细

(转)CComPtr和CComQIPtr

时间:2015-05-15 15:21:25      阅读:116      评论:0      收藏:0      [点我收藏+]

标签:

CComPtr和CComQIPtr是智能接口指针类,它们在销毁的时候,不需要手动去释放接口指针,在赋值的时候,也不需要手动的AddRef,在出现异常的时候,会自动处理异常,而不需要额外的异常处理代码。

 

     CComPtr和CComQIPtr的不同的地方:CComPtr只能创建固定的特定的接口指针实例。而CComQIPtr不但实现了CComPtr的所有的功能,而且当我们把一个不同类型的接口指针赋值给CComQIPtr的时候,CComQIPtr会自动的调用接口指针的QueryInterface接口,来获得对应的正确的接口指针。

 

     (1) 构造函数

            第一个参数为智能接口指针的类型,第二个参数为 智能指针的接口ID。

 

            CComPtr<IUnknown> punk;

 

            //下面三个例子完全相同

            CComPtr<IXXX> pno;

            CComPtr<IXXX,&__uuidof(IXXX)> pno;

            CComPtr<IXXX,&IID_IXXX> pno;

 

      CComQIPtr可以用任何一个类型的接口指针初始化,如果初始化的值与CComQIPtr的类型相同,那么构造函数简单调用 指针的AddRef,但是,如果类型不同的话,它会先调用指针的QueryInterface来获得相同的类型的接口指针,当QueryInterface失败的话,内部指针会被设置为NULL。

           所有下面的代码,可以用来检测是否转换成功:

           

[cpp] view plaincopy
 
  1. void  Func(IUnknown * punk)  
  2.   
  3. {  
  4.   
  5.       CComQIPtr<IXXX> pno(punk);  
  6.   
  7.       if(pno)  
  8.   
  9.      {  
  10.   
  11.         //正确转换  
  12.   
  13.         pno->doSomething();  
  14.   
  15.      }  
  16.   
  17. }  

 

 

 

      (2)赋值

          赋值的时候,发生下面三件事:

          111.  如果当前指针不为空,那么释放当前指针

          222.   如果源指针不为空,那么AddRef

          333.   将当前指针设置为源指针

 

     oprator =  可以让我们把任何一个CComPtr赋值给CComQIPtr对象,如果有必要就会调用QueryInterface .

 

           例如:

          

[cpp] view plaincopy
 
  1. CComQIPtr<IFoo>   fooPtr;  
  2.   
  3. CComQIPtr<IBar>    barPtr;  
  4.   
  5.   
  6.   
  7. barPtr=fooPtr;  

 

 

    (3)  CoCreateInstance方法

         CComPtr提供了一个实例化对象的方法

 

          HRESULT   CoCreateInstance(REFCLSID  rclsid,LPUNKNOWN  pUnkOuter=NULL, DWORD dwClsCOntext=CLSCTX_ALL);

 

 

          HRESULT   CoCreateInstance(LPCOLESTR szProgID, LPUNKNOSWN

pUnkOuter=NULL, DWORD  dwClsContxt=CLSCTX_ALL);

 

         后两个参数不管,第一个参数要不传入CLSID,要不传入字符串形式的progID.

        

        例子代码如下:

       

[cpp] view plaincopy
 
  1. CComPtr<IXXX> ptr;  
  2.   
  3. HRESULT  hr=ptr.CoCreateInstance(__uuidof(IXXX));  

 

 

      

 

      (4)  operator *()

          当对CComPtr解除指针的引用时,跟普通的指针一样,返回一个内部指针类型的引用。

 

     (5)   operator &()

 

          获取智能指针对象的地址,实际上也是返回内部指针的地址,跟普通指针一样。

 

     (6)  在调用ComUninitialize方法前,需要手动释放所有的全局或者静态变量。

 

            如何手动释放呢:

            111.设置指针指向NULL

            222.调用Release方法,注意是要调用智能指针的Release方法,而不是内部指针的,指针指针的Release方法,会调用内部指针的Relase,然后设置内部指针为NULL,这样就可以防止多次释放接口。

 

     (7)CopyTo方法,拷贝后的智能指针生命周期完全独立。

 

            我们用CopyTo方法,将指针拷贝到一个out型参数。

 

      (8)Detach 和Attach方法

 

           在返回一个我们不再需要的接口指针给调用者的时候,我们可以用Deatch方法。

 

            当我们需要把原始指针的所有权转移到智能指针时候,用Attach方法。

 

 

       (9)  QueryInterface方法

              他只需要传入期望获得的接口类型的变量地址,即可。

 

              CComPtr<IFoo>   pFoo=...;

 

              CComPtr<IBar>   pBar;

 

              HRESULT   hr= pFoo.QueryInterface(&pBar);

 

       (10)  IsEqualObject方法

               IsEqualObject方法用来判断两个接口指针释放引用的是同一个对象。

 

              

 

       (11)  !=  和 ==  操作符

 

               跟普通的 一样

 

       (12)  CComPtr对IDispatch的特化

 

               CComPtr<IDispatch>  iptr;

 

               属性调用的辅助函数

               111.  GetIDOfName(LPCOLESTR  lpsz,DISPID  * pdispid)

                        这个方法,获得属性的DISPID

 

                222.GetProPerty(DISPID  dwDispid,  VARIANT *  pVar)

                       这个方法,获得属性。

                       SetProPerty(DISPID  dwDispid,  VARIANT *  pVar)

                       这个方法,设置属性。

 

               333. GetPropertyByName(LPCOLESTR lpsz, VARIANT * pVar)

                       SetPropertyByName(LPCOLESTR lpsz, VARIANT * pVar)

                       直接通过名称,获得和设置属性。

 

 

                            

               方法调用的辅助函数:

               111. HRESULT  Invoke0(DISPID dispid,VARIANT * pvarRet=NULL);

                       通过DISPID调用 没有参数的方法。

 

                       HRESULT  Invoke0(LPCOLESTR  lpszName, VARIANT * pvarRet=NULL);

                       通过方法名称,调用没有参数的方法。

 

                       HRESULT  Invoke1(DISPID dispid,VARIANT * param1, VARIANT *

pvarRet=NULL);

                       通过DISPID调用 有一个参数的方法。

 

                       HRESULT  Invoke1(LPCLOESTR  lpszName ,VARIANT * param1,

VARIANT * pvarRet=NULL);

                       通过方法名称,调用有一个参数的方法。

 

 

                       HRESULT  InvokeN(DISPID dispid,VARIANT* params, int  nParams,   VARIANT * pvarRet=NULL);

                       通过DISPID调用有N个参数的方法。

 

                       HRESULT InvokeN(LPCLOESTR   lpszName ,VARIANT * params,int  nParams,  VARIANT * pvarRet=NULL);

                      通过方法名称调用有N个参数的方法。

 

                       注意,通过参数列表的方法调用的时候,参数是反向的顺序,最后一个参数是元素0。  切记。

 

原文:http://blog.csdn.net/tangaowen/article/details/6554753

(转)CComPtr和CComQIPtr

标签:

原文地址:http://www.cnblogs.com/wangfs/p/4505751.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!