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 IXIUnknown{/**/}

Interface IYIUnknown{/**/}

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