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的基址加上偏移址。