分享

CComPtr和CComQIPtr

 猎狐肥 2019-09-24

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。

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

  1. void  Func(IUnknown * punk)  

  2. {  

  3.       CComQIPtr<IXXX> pno(punk);  

  4.       if(pno)  

  5.      {  

  6.         //正确转换  

  7.         pno->doSomething();  

  8.      }  

  9. }  

      (2)赋值

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

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

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

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

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

           例如:

  1. CComQIPtr<IFoo>   fooPtr;  

  2. CComQIPtr<IBar>    barPtr;  

  3. 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.

        例子代码如下:

  1. CComPtr<IXXX> ptr;  

  2. 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

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多