Six, com_interface_entry_aggregate_blind Part ITL RROR COMMAP Previous We talked about com_interface_entry_aggregate, the macro to be introduced in this section is very similar.
#DEfine COM_ITERFACE_ENTRY_AGGREGATE_BLIND (PUNK) / {NULL, / (DWORD) Offsetof (_Commapclass, punk), / _dlegate},
As can be seen from the definition, it is the only difference between the introduction to the previous section is that it does not specify the interface ID! !
So the first item in its definition is NULL.
This macro is used in the same way as our com_interface_entry_aggregate. You can refer to the previous section and the ATL routine COMMAP.
Let's take a look at the related code in atlinternalQueryInterface ().
ATLINLINE ATLAPI AtlInternalQueryInterface (void * pThis, const _ATL_INTMAP_ENTRY * pEntries, REFIID iid, void ** ppvObject) {// If IUnknown, .... while (pEntries-> pFunc! = NULL) {BOOL bBlind = (pEntries-> PIID == NULL); if (bblind || inlineisequalguid (* (pentries-> piid), IID)) {if (pentries-> pfunc == _tl_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;}}}}}}} Return E_NOINTERFACE;} Note Variable BBLIND: BOOL BBLIND = (Pentries-> PIID == NULL);
If the interface ID is not specified, continue to perform the following operations, it can be seen that even if the IID we need, _Delegate will be performed.
As can be seen from the above, this macro is suitable for a case where a gathering component has multiple interfaces, so as long as it is querying the interface of this aggregation component, it will enter the _dlegate function. But special attention is the location of this macro! ! For example, if this is the order:
Begin_COM_MAP COM_INTERFACE_ENTRY_AGGREGATE_BLIND (m_punkagblind.p) COM_INTERFACE_ENTRY (IOUTER) End_com_map When Query IOUTER interface, it will be wrong! ! !
Seven, com_interface_entry_autoaggregate (IID, PUNK, CLSID) First look at this macro definition:
#define COM_INTERFACE_ENTRY_AUTOAGGREGATE (iid, punk, clsid) / {& iid, / (DWORD) & _ CComCacheData CComAggregateCreator <_ComMapClass, & clsid>, / (DWORD) offsetof (_ComMapClass, punk) /> :: data, / _Cache},
Let's take a look at its typical usage:
class CAutoAgg: public IDispatchImpl
With the general components and no numbers.
class COuter: public CChainBase, public IDispatchImpl, public CComCoClass {BEGIN_COM_MAP (COuter) COM_INTERFACE_ENTRY_AUTOAGGREGATE (IID_IAutoAgg, m_pUnkAutoAgg.p, CLSID_CAutoAgg) END_COM_MAP () CComPtr m_pUnkAutoAgg;};
Unlike the macro COM_ITERFACE_ENTRY_AGGREGRATE (_), COUTER does not have to create a gathering component in FinalConstruct. External components will automatically create aggregated components! ! !
1.
Template
2.
static HRESULT WINAPI _Cache (void * pv, REFIID iid, void ** ppvObject, DWORD dw) {HRESULT hRes = E_NOINTERFACE; _ATL_CACHEDATA * pcd = (_ATL_CACHEDATA *) dw; IUnknown ** pp = (IUnknown **) ((DWORD) PV PCD-> dwoffsetvar; if (* pp == null) hres = pcd-> PFUNC (PV, IID_IUNKNOWN, (VOID **) PP); if (* pp! = null) hres = (* pp) - > Queryinterface (IID, ppvobject); return hres;}
3.
template
Compared with the macro COM_INTERFACE_ENTRY_AGGREGATE, this macro seems to be better, only when it is needed, it is easier to use.
Eight, com_interface_entry_autoaggregate_blind (Punk, CLSID)
Take a look at its definition:
#define COM_INTERFACE_ENTRY_AUTOAGGREGATE_BLIND (punk, clsid) / {NULL, / (DWORD) & _ CComCacheData CComAggregateCreator <_ComMapClass, & clsid>, / (DWORD) offsetof (_ComMapClass, punk) /> :: data, / _Cache},
Oh, this macro combines the characteristics of com_interface_entry_autoaggregate () and COM_ITERFACE_ENTRY_AGGREGATE_BLIND (), which can automatically create multiple interfaces in the aggregated component. No longer! !