COM学习笔记(三)IUnknown接口

一: 接口定义

    任何一个接口都是继承于IUnknown接口。

  客户同组件的交互都是通过一个接口完成的。在客户查询组件的其他接口时,也是通过接口完成的。这个接口就是Iunkown,它的定义包含在Win32 SDK中的UNKOWN.h头文件中。

[cpp]  view plain copy
  1. interface IUnkown  
  2.   
  3. {  
  4.   
  5.    virtual HRESULT __stdcall QueryInterface(const IID& iid, void** ppv) = 0;  
  6.   
  7.    virtual ULONG __stdcall AddRef() = 0;  
  8.   
  9.    virtual ULONG __stdcall Release() = 0;  
  10.   
  11. };  

         

2.      获取IUnkown指针

   有一个叫CreateInstance的函数,它可以建立一个组件并返回一个IUkown指针:

     IUnkown* CreateInstance();

    在此,客户不必再使用new操作符

3. QueryInterface函数

    客户可使用IUnkown中的成员函数QueryInterface查询组件是否支持某个特定的接口,如果支持,将返回一个指向此接口的指针;如果不支持,则返回一个错误代码。

   HRESULT __stdcall QueryInterface(const IID& iid, void** ppv);

     其中,第一个参数iid标志客户所需的接口,第二个参数ppv存放所请求接口的指针地址。

4.  使用QueryInterface

[cpp]  view plain copy
  1. IUnkown* pI;  
  2. //define a pointer for the interface  
  3. IX* pIX = NULL;  
  4. //ask for interface IX  
  5. HRESULT hr = pI->QueryInterface(IID.IX, (void**) &pIX);  
  6. //check return value  
  7. if(SUCCEEDED(hr))  
  8. {  
  9.    //use interface  
  10.    pIX->fx();  
  11. }  

在这段代码中,我们查询了pI是否支持由IID.IX所标识的接口。若成功返回,那么我们就可以使用它返回的指针了。

 

5. QueryInterface的实现

   QueryInterface需要根据某个给定的IID返回指向相应接口的指针。如果组件支持客户指定的接口,那么返回S_OK及相应的指针,否则,返回E_NOINTERFACE并将相应的指针返回值设为NULL。

例如我们有类CA,及其接口的继承关系:

[cpp]  view plain copy
  1. HRESULT __stdcall CA::QueryInterface(const IID& iid, void** ppv)  
  2. {  
  3.       if(iid == IID.IUnkown)  
  4.       {  
  5.   
  6.               //the client wants the IUnkown interface  
  7.               *ppv = static_cast<IX*>(this);  
  8.        }  
  9.        else if(iid == IDD.IX)  
  10.        {  
  11.               //the client wants the IX interface  
  12.               *ppv = static_cast<IX*>(this);  
  13.        }  
  14.        else if (iid == IDD.IY)  
  15.        {  
  16.               //the client wants the IY interface  
  17.               *ppv = static_cast<IY*>(this);  
  18.        }  
  19.        else  
  20.        {  
  21.              //we don't support the interface the client wants.  
  22.               //be sure to set the resulting pointer to NULL  
  23.               *ppv = NULL;  
  24.               return E_NOINTERFACE;  
  25.        }  
  26.        static_cast<IUnkown*>(*ppv)->AddRef();  
  27.        return S_OK;  
  28. }  

在这里,QueryInterface使用一个简单的if-then-else语句实现。当然用其他任何一种可以将一种类型映射成另外一种类型的结构也是可以实现的。如可用数组、哈希表或树来实现。

6.  QueryInterface的实现规则

(1)       QueryInterface必须总是返回同一IUnkown指针

可以通过查询两个接口的IUnkown接口,并比较其返回值来确定这两个接口是否指向同一组件。

(2)       若客户曾经获取过某个接口,那么它将总能获取此接口

(3)       客户可以再次获取已经拥有的接口

(4)       客户可以返回到起始接口

(5)       若能够从某个接口获取某特定接口,那么可以从任意接口都将可以获取此接口

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值