AC8,由VS2005的ATL向导生成的默认COM对象代码分析ATL如何实现COM,第八部分。
接口三剑客AddRef、Release、QueryInterface不用说了,他是在CComObjectRootEx中被实现的,但是调用过程却不是简单的依照虚函数路线向上查找到了这个类,而是由通过了系列宏BEGIN_COM_MAP。
已经说过,我们使用ATL向导添加的class不是最终的com对象,而是该对象的基类,也就是说三剑客被调用的入口点应该是CComObject(或CComAggObject)类。分析BEGIN_COM_MAP组宏可以发现一些不太明显的细节。
仍以XXX类示例,这组宏可能是这样:
BEGIN_COM_MAP(CMeee)
COM_INTERFACE_ENTRY(IMeee)
COM_INTERFACE_ENTRY(IDispatch)
END_COM_MAP()
END_COM_MAP中有三个非常重要的定义:
virtual ULONG STDMETHODCALLTYPE AddRef( void) throw() = 0;
virtual ULONG STDMETHODCALLTYPE Release( void) throw() = 0;
STDMETHOD(QueryInterface)(REFIID, void**) throw() = 0;
这组声明让调用明朗起来,三剑客必须是有XXX的继承类实现的,这与我先前说的三剑客由CComObjectRootEx实现不符,其实并不冲突,查看CComObject、CComAggObject类知道,
STDMETHOD_(ULONG, AddRef)() {return InternalAddRef();}
STDMETHOD_(ULONG, Release)()

本文分析了ATL COM对象的创建过程中,BEGIN_COM_MAP宏如何影响接口的实现和调用。接口的关键成员AddRef、Release、QueryInterface实现在CComObjectRootEx中,但调用是通过BEGIN_COM_MAP完成。接口调用的实际入口位于CComObject或CComAggObject的派生类,其中AddRef和Release直接转发,QI则通过_InternalQueryInterface和InternalQueryInterface实现。文中还探讨了offsetofclass宏和_ATL_INTMAP_ENTRY结构的作用。
&spm=1001.2101.3001.5002&articleId=2543957&d=1&t=3&u=20e9a2cac0d04d3e919bd916e2638e51)
666

被折叠的 条评论
为什么被折叠?



