COM 学习笔记
QueryInterface函数
主要用于COM接口的查询。它是COM接口定义IUnknown的成员函数,客户可以调用QueryInterface来决定组件是否支持某个特定的接口。
组件COM接口都是从IUnkonwn接口继承而来,任何一个接口都可以用IUnknown的成员QueryInterface来获取它所支持的其它接口。
1)定义:
HRESULT
_stdcall QueryInterface(const IID& iid,void ** ppv);
第一个参数十所需接口的标识,是一个接口标识符IID结构。 第二个参数存放所请求接口指针的地址。
2)使用过程:
假定已有一个指向IUnknown的指针pI,为知道相应的组件是否支持某个特定的接口,调用QueryInterface,传给它一个接口标识符。若成功返回,那就是可以使用它返回的指针。
Void
foo(IUnknown * pI)
{
IX *pIX=NULL;
HRESULT hr=pI->QueryInterface(IID_IX,(void **)&pIX);
If(SUCCEEDED(hr))
pIX->Fx();
}
该函数用于查询pI是否支持由IID_IX所标识的接口。
IUnknown的继承不是虚拟基类。COM接口不能按照虚拟方式继承它。
3)实现:
Interface IX:IUnknown{/**/};
Interface IY:IUnknown{/**/};
Class CA:public IX,public IY{/**/};
主要通过判断标识符是否为CA的支持类型,来判断是否为存在在CA中的COM
HRESULT
_stdcall CA:;QueryInterface(const IID &iid,void **ppv)
{
If(iid==IID_IUnknown)
{
*ppv=static_cast<IX
*>(this);
}
Else if(iid==IID_IX)
{
*ppv=static_cast<IX*>(this);
}
Else if (iid==IID_IY)
{
*ppv=static_cast<IY*>(this);
}
Else
{
*ppv=NULL;
Return E_NOINTERFACE;
}
Static_cast<IUnknown*>(*ppv)->AddRef();
Return S_OK;
}
4)关于其中的类型转换
程序中若将this指针直接转换成IUnknown*是不明确的。因为存在两个基类接口,需要指明是转换向哪一个接口的IUnknown。
Static_cast<IUnknown*>
(static_cast<IX *>(this))
在类型转换时,CA按照顺序存放它的基类接口及其实现,其this指针可以用IX代替(地址值相同)。
而IY则需要CA的基址加上偏移址。