IUnkown接口和QueryInterface函数

本文介绍了COM中的IUnknown接口,包括其定义、作用以及如何使用QueryInterface查询组件支持的接口。并通过实例展示了QueryInterface的实现方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.       IUnkown接口

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

interface IUnkown

{

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

   virtual ULONG __stdcall AddRef() = 0;

   virtual ULONG __stdcall Release() = 0;

};

客户可以调用QueryInterface函数来决定组件是否支持某个特定的接口。所有的COM接口都需要继承IUnkown,因而每个COM接口的vTable中的前三个函数都是QueryInterfaceAddRefRelease。这使得所有的COM接口都可以被当成IUnkown接口来处理。

2.       获取IUnkown指针

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

IUnkown* CreateInstance();

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

3.       QueryInterface函数

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

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

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

4.       使用QueryInterface

IUnkown* pI;

//define a pointer for the interface

IX* pIX = NULL;

//ask for interface IX

HRESULT hr = pI->QueryInterface(IID.IX, (void**) &pIX);

//check return value

if(SUCCEEDED(hr))

{

//use interface

pIX->fx();

}

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

5.       QueryInterface的实现

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

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

下面的代码实现类CAQueryInterface,它可以返回三种不同接口的指针:IUnkownIXIY

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

{

       if(iid == IID.IUnkown)

       {

              //the client wants the IUnkown interface

              *ppv = static_cast<IX*>(this);

       }

       else if(iid == IDD.IX)

       {

              //the client wants the IX interface

              *ppv = static_cast<IX*>(this);

       }

       else if (iid == IDD.IY)

       {

              //the client wants the IY interface

              *ppv = static_cast<IY*>(this);

       }

       else

       {

              //we don't support the interface the client wants.

              //be sure to set the resulting pointer to NULL

              *ppv = NULL;

              return E_NOINTERFACE;

       }

       static_cast<IUnkown*>(*ppv)->AddRef();

       return S_OK;

}

在这里,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、付费专栏及课程。

余额充值