六、COM_INTERFACE_ENTRY_AGGREGATE_BLIND 參ATL常式COMMAP
上一節我們講了COM_INTERFACE_ENTRY_AGGREGATE,這節要介紹的宏與它很類似。
#define COM_INTERFACE_ENTRY_AGGREGATE_BLIND(punk)/
{NULL,/
(DWORD)offsetof(_ComMapClass, punk),/
_Delegate},
從定義上就可以看出,它與上一節介紹宏的唯一區別就在於,它沒有指明介面ID!!
所以在它的定義中第一項也是NULL。
這個宏的用法與我們COM_INTERFACE_ENTRY_AGGREGATE一模一樣。大家可以參考上一節
內容以及ATL的常式COMMAP。
我們來看看AtlInternalQueryInterface()中的相關代碼。
ATLINLINE ATLAPI AtlInternalQueryInterface(void* pThis,
const _ATL_INTMAP_ENTRY* pEntries, REFIID iid, void** ppvObject)
{
//如果是IUnknown,....
while (pEntries->pFunc != NULL)
{
BOOL bBlind = (pEntries->piid == NULL);
if (bBlind || InlineIsEqualGUID(*(pEntries->piid), iid))
{
if (pEntries->pFunc == _ATL_SIMPLEMAPENTRY) //offset
{
ATLASSERT(!bBlind);
IUnknown* pUnk = (IUnknown*)((int)pThis+pEntries->dw);
pUnk->AddRef();
*ppvObject = pUnk;
return S_OK;
}
else
{
HRESULT hRes = pEntries->pFunc(pThis,
iid, ppvObject, pEntries->dw);
if (hRes == S_OK || (!bBlind && FAILED(hRes)))
return hRes;
}
}
pEntries++;
}
return E_NOINTERFACE;
}
}
注意變數bBlind;
BOOL bBlind = (pEntries->piid == NULL);
若沒指定介面ID,也繼續執行後面的操作,可見即使並非我們所需要的IID,也會執行
_Delegate.
從上可見,這個宏適用於一個聚集組件有多個介面的情況,這樣只要是查詢這個聚集組
件的介面,就會進入_Delegate函數。但要特別注意的是這個宏的位置!!
比如若是這樣的順序:
BEGIN_COM_MAP
COM_INTERFACE_ENTRY_AGGREGATE_BLIND(m_pUnkAggBlind.p)
COM_INTERFACE_ENTRY(IOuter)
END_COM_MAP
當查詢IOuter介面時就會出錯!!!