用嵌套类实现COM接口(续三) HRESULT CDIctionary: QueryInterface( const lID& iid, void **ppvobj) if(iid=lID IUnknown iid=IID Dictionary)i Fppvobj=&m dictionary AddRef( return s oK 3 else if (iid=IID SpellCheck) "ppvObj=&m spellCheckobj AddRefo return S OK "ppV= NULL return E INTerface
用嵌套类实现COM接口(续三) HRESULT CDictionary::QueryInterface(const IID& iid, void **ppvObj) { if (iid == IID_IUnknown || iid == IID_Dictionary) { *ppvObj = &m_dictionaryObj; AddRef(); return S_OK; } else if (iid == IID_SpellCheck) { *ppvObj = &m_spellCheckObj; AddRef(); return S_OK; } *ppv = NULL; return E_NOINTERFACE ; }
用嵌套类实现COM接口(续四 ULONG CDictionary: XDictionaryObj: QueryInterface( const IID& iid Did**ppvobj return m pParent->QueryInterface(iid, ppvobj); ULONG CDictionary: XDictionary Ob AddRefo return m pParent->AddRefo ULONG CDictionary: XDictionary Ob Release return m pParent->Release (
用嵌套类实现COM接口 (续四 ) ULONG CDictionary::XDictionaryObj::QueryInterface(const IID& iid, void **ppvObj) { return m_pParent->QueryInterface(iid, ppvObj); } ULONG CDictionary::XDictionaryObj::AddRef() { return m_pParent->AddRef(); } ULONG CDictionary::XDictionaryObj::Release () { return m_pParent->Release (); }
“用嵌套类实现COM接口”原理 DIctionary Vtable for Dictionary m_dictionaryObjlptr7 Querylnterface AddRef m spell CheckObi /vptr Release m pData m Dict Filename[ 128 Vtable for ISpell Check m ref QueryInterface m n WordNumber AddRef m nStructNumber R elease Querylnterface CDictiona的0函数 AddRef Release
“用嵌套类实现COM接口”原理 m_pData m_DictFilename[128] m_Ref m_nWordNumber m_nStructNumber QueryInterface AddRef Release ……. m_dictionaryObj m_spellCheckObj QueryInterface AddRef Release …… QueryInterface AddRef Release …… Vtable for IDictionary Vtable for ISpellCheck CDictionary vptr vptr CDictionary的非虚函数
MFC:接口映射表 CCmdTarget类 CCmd Target: m dwRef为引用计数 接口映射表与消息映射表非常类似 接口映射表:记录了 CCmdtarget)中每一个嵌套类的接 口ID以及接口 vtable与父类this指针之间的偏移量 offsetof宏:成员类与父类之间的偏移值
MFC:接口映射表 • CCmdTarget类 • CCmdTarget::m_dwRef为引用计数 • 接口映射表与消息映射表非常类似 • 接口映射表:记录了CCmdTarget类中每一个嵌套类的接 口ID以及接口vtable与父类this指针之间的偏移量 • offsetof宏:成员类与父类之间的偏移值
DECLARE INTERFACE MAP #define DECLARE INTERFACE MAPO\ privat static const AFX INTERFACEMAP ENTRY interface Entries; I otected: l static AFX DATA const AFX INTERFACEMAP interface Map; I static const AFX INTERFACEMAP* PASCAL GetBaselnterface MapO; I virtual const AFX INTERFACEMAP* GetInterfaceMap( const; I struct AFX INTERFACEMAP ENTRY struct AFX INTERFACEMAP const void*piid; #ifdef aFXdll size t oFfset; const AFX INTERFACEMAP*(PASCAL pfn GetBaseMap)o #else const AFX INTERFACEMAP" pBase Map #endif const AFX INTERFACEMAP ENTRY* pEntry
DECLARE_INTERFACE_MAP #define DECLARE_INTERFACE_MAP() \ private: \ static const AFX_INTERFACEMAP_ENTRY _interfaceEntries[]; \ protected: \ static AFX_DATA const AFX_INTERFACEMAP interfaceMap; \ static const AFX_INTERFACEMAP* PASCAL _GetBaseInterfaceMap(); \ virtual const AFX_INTERFACEMAP* GetInterfaceMap() const; \ struct AFX_INTERFACEMAP_ENTRY { const void* piid; size_t nOffset; }; struct AFX_INTERFACEMAP { #ifdef _AFXDLL const AFX_INTERFACEMAP* (PASCA L pfnGetBaseMap)(); #else const AFX_INTERFACEMAP* pBaseMap; #endif const AFX_INTERFACEMAP_ENTRY* pEntry; };