﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-Heaven On Programming</title><link>http://www.cppblog.com/HeavenOnProg/</link><description>蕴无法于有法，化有限为无限</description><language>zh-cn</language><lastBuildDate>Wed, 22 Apr 2026 13:42:30 GMT</lastBuildDate><pubDate>Wed, 22 Apr 2026 13:42:30 GMT</pubDate><ttl>60</ttl><item><title>ATL对接口查询的支持</title><link>http://www.cppblog.com/HeavenOnProg/archive/2007/04/30/23233.html</link><dc:creator>michael</dc:creator><author>michael</author><pubDate>Mon, 30 Apr 2007 03:37:00 GMT</pubDate><guid>http://www.cppblog.com/HeavenOnProg/archive/2007/04/30/23233.html</guid><wfw:comment>http://www.cppblog.com/HeavenOnProg/comments/23233.html</wfw:comment><comments>http://www.cppblog.com/HeavenOnProg/archive/2007/04/30/23233.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/HeavenOnProg/comments/commentRss/23233.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/HeavenOnProg/services/trackbacks/23233.html</trackback:ping><description><![CDATA[
		<p>COM对象实现接口的方法是多种多样的，常用的有多重继承、聚合、tear-off等。为了最大限度地支持接口查询的多样性，ATL使用表驱动的方式来管理接口查询，以做到代码封闭和扩展灵活，表条目格式为：<br /><br /></p>
		<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee">
				<span style="COLOR: #0000ff">struct</span>
				<span style="COLOR: #000000"> _ATL_INTMAP_ENTRY<br />{<br />    </span>
				<span style="COLOR: #0000ff">const</span>
				<span style="COLOR: #000000"> IID</span>
				<span style="COLOR: #000000">*</span>
				<span style="COLOR: #000000"> piid; </span>
				<span style="COLOR: #008000">
						<br />
				</span>
				<span style="COLOR: #000000">    DWORD_PTR dw;<br />    _ATL_CREATORARGFUNC</span>
				<span style="COLOR: #000000">*</span>
				<span style="COLOR: #000000"> pFunc; <br /></span>
				<span style="COLOR: #000000">};</span>
		</div>
		<p>
				<br />piid是接口ID，dw为自定义参数，pFunc是自定义函数的地址。在QueryInterface时，ATL调用pFunc，并将dw传给pFunc，pFunc可以根据自己的需要解析dw，获得查询必需的信息。ATL预提供了一些函数来处理上述常用的查询请求，如_Creator、_Delegate等，它们被放置于CComObjectRootBase中。<br /></p>
		<p>（1）多重继承<br />           ATL并没有提供支持多重继承的函数，而是将pFunc设置为_ATL_SIMPLEMAPENTRY宏，将dw设为父类子对象在子类对象中的偏移量，当搜索表时发现pFunc为_ATL_SIMPLEMAPENTRY时，便直接使用偏移量相加获得结果。</p>
		<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee">
				<span style="COLOR: #0000ff">            if</span>
				<span style="COLOR: #000000"> (pEntries</span>
				<span style="COLOR: #000000">-&gt;</span>
				<span style="COLOR: #000000">pFunc </span>
				<span style="COLOR: #000000">==</span>
				<span style="COLOR: #000000"> _ATL_SIMPLEMAPENTRY) </span>
				<span style="COLOR: #008000">
						<br />
				</span>
				<span style="COLOR: #000000">            {<br /></span>
				<span style="COLOR: #000000">                IUnknown</span>
				<span style="COLOR: #000000">*</span>
				<span style="COLOR: #000000"> pUnk </span>
				<span style="COLOR: #000000">=</span>
				<span style="COLOR: #000000"> (IUnknown</span>
				<span style="COLOR: #000000">*</span>
				<span style="COLOR: #000000">)((INT_PTR)pThis</span>
				<span style="COLOR: #000000">+</span>
				<span style="COLOR: #000000">pEntries</span>
				<span style="COLOR: #000000">-&gt;</span>
				<span style="COLOR: #000000">dw);<br />                pUnk</span>
				<span style="COLOR: #000000">-&gt;</span>
				<span style="COLOR: #000000">AddRef();<br />                </span>
				<span style="COLOR: #000000">*</span>
				<span style="COLOR: #000000">ppvObject </span>
				<span style="COLOR: #000000">=</span>
				<span style="COLOR: #000000"> pUnk;<br />                </span>
				<span style="COLOR: #0000ff">return</span>
				<span style="COLOR: #000000"> S_OK;<br />            }</span>
		</div>
		<br />
		<p>         接口映射表项宏为：</p>
		<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee">
				<span style="COLOR: #0000ff">         #define</span>
				<span style="COLOR: #000000"> COM_INTERFACE_ENTRY(x)\</span>
				<span style="COLOR: #000000">
						<br />             {</span>
				<span style="COLOR: #000000">&amp;</span>
				<span style="COLOR: #000000">_ATL_IIDOF(x), \<br />             offsetofclass(x, _ComMapClass), \<br />             _ATL_SIMPLEMAPENTRY},</span>
		</div>
		<p>
				<br />（2）聚合<br />           ATL使用_Delegate函数来支持聚合，此时dw存储的是内部对象指针成员变量在外部对象中的偏移量，_Delegate利用此偏移量获得内部对象指针，然后将查询调用委托给它。</p>
		<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee">
				<span style="COLOR: #0000ff">    static</span>
				<span style="COLOR: #000000"> HRESULT WINAPI _Delegate(</span>
				<span style="COLOR: #0000ff">void</span>
				<span style="COLOR: #000000">*</span>
				<span style="COLOR: #000000"> pv, REFIID iid, </span>
				<span style="COLOR: #0000ff">void</span>
				<span style="COLOR: #000000">**</span>
				<span style="COLOR: #000000"> ppvObject, DWORD_PTR dw)<br />    {<br />        HRESULT hRes </span>
				<span style="COLOR: #000000">=</span>
				<span style="COLOR: #000000"> E_NOINTERFACE;<br />        IUnknown</span>
				<span style="COLOR: #000000">*</span>
				<span style="COLOR: #000000"> p </span>
				<span style="COLOR: #000000">=</span>
				<span style="COLOR: #000000"> </span>
				<span style="COLOR: #000000">*</span>
				<span style="COLOR: #000000">(IUnknown</span>
				<span style="COLOR: #000000">**</span>
				<span style="COLOR: #000000">)((DWORD_PTR)pv </span>
				<span style="COLOR: #000000">+</span>
				<span style="COLOR: #000000"> dw);<br />        </span>
				<span style="COLOR: #0000ff">if</span>
				<span style="COLOR: #000000"> (p </span>
				<span style="COLOR: #000000">!=</span>
				<span style="COLOR: #000000"> NULL)<br />            hRes </span>
				<span style="COLOR: #000000">=</span>
				<span style="COLOR: #000000"> p</span>
				<span style="COLOR: #000000">-&gt;</span>
				<span style="COLOR: #000000">QueryInterface(iid, ppvObject);<br />        </span>
				<span style="COLOR: #0000ff">return</span>
				<span style="COLOR: #000000"> hRes;<br />    }</span>
		</div>   <br />         接口映射表项宏为：<br /><br /><div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #0000ff">      #define</span><span style="COLOR: #000000"> COM_INTERFACE_ENTRY_AGGREGATE(iid, punk)\</span><span style="COLOR: #000000"><br />          {</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">iid,\<br />          (DWORD_PTR)offsetof(_ComMapClass, punk),\<br />          _Delegate},</span></div>   <br />（3）tear-off<br />           ATL使用_Creator函数来支持tear-off，此时dw中存储的是一个静态_ATL_CREATORDATA结构的地址，_Creator利用其中的指向创建函数的指针创建一个tear-off对象。<br />                   
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #0000ff">         static</span><span style="COLOR: #000000"> HRESULT WINAPI _Creator(</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000"> pv, REFIID iid, </span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">**</span><span style="COLOR: #000000"> ppvObject, DWORD_PTR dw)<br />         {<br />              _ATL_CREATORDATA</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000"> pcd </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> (_ATL_CREATORDATA</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">)dw;<br />              </span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000"> pcd</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">pFunc(pv, iid, ppvObject);<br />         }</span></div><br />         接口映射表项宏为：<br />             
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #0000ff">      #define</span><span style="COLOR: #000000"> COM_INTERFACE_ENTRY_TEAR_OFF(iid, x)\</span><span style="COLOR: #000000"><br />          {</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">iid,\<br />          (DWORD_PTR)</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">ATL::_CComCreatorData</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">\<br />              ATL::CComInternalCreator</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000"> ATL::CComTearOffObject</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000"> x </span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">\<br />              </span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">::data,\<br />          _Creator},</span></div><br />      _ComCreatorData的相关定义如下：<br />      
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #0000ff">struct</span><span style="COLOR: #000000"> _ATL_CREATORDATA<br />{<br />    _ATL_CREATORFUNC</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000"> pFunc;<br />};<br /><br />template </span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000"> Creator</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br /></span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000"> _CComCreatorData<br />{<br /></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:<br />    </span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000"> _ATL_CREATORDATA data;<br />};<br /><br />template </span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000"> Creator</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br />_ATL_CREATORDATA _CComCreatorData</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">Creator</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">::data </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> {Creator::CreateInstance};</span></div><br /><br />      我们还可以定义自己的接口查询辅助函数和辅助数据，通过dw和pFunc来完成各种千奇百怪的接口实现方式，需要的只是想象力。<img src ="http://www.cppblog.com/HeavenOnProg/aggbug/23233.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/HeavenOnProg/" target="_blank">michael</a> 2007-04-30 11:37 <a href="http://www.cppblog.com/HeavenOnProg/archive/2007/04/30/23233.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ATL对对象创建的支持</title><link>http://www.cppblog.com/HeavenOnProg/archive/2007/04/10/21605.html</link><dc:creator>michael</dc:creator><author>michael</author><pubDate>Tue, 10 Apr 2007 09:36:00 GMT</pubDate><guid>http://www.cppblog.com/HeavenOnProg/archive/2007/04/10/21605.html</guid><wfw:comment>http://www.cppblog.com/HeavenOnProg/comments/21605.html</wfw:comment><comments>http://www.cppblog.com/HeavenOnProg/archive/2007/04/10/21605.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/HeavenOnProg/comments/commentRss/21605.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/HeavenOnProg/services/trackbacks/21605.html</trackback:ping><description><![CDATA[         在COM中对象要通过class factory的接口（通常是IClassFactory）来创建。在ATL中，class factory也是从CComObjectRootEx派生的COM类，它跟普通的COM类一样，也通过CComObject或其同伴类将逻辑功能跟生存期管理分离。<br />         在ATL中，class factory类和普通类对象的创建都可以通过被称为“创建者”的模板类来创建。<br />          
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #000000">template </span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000"> T1</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br /></span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000"> CComCreator<br />{<br /></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:<br />    </span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000"> HRESULT WINAPI CreateInstance(</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000"> pv, REFIID riid, LPVOID</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000"> ppv)<br />    {<br /></span><span style="COLOR: #000000">        HRESULT hRes </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> E_OUTOFMEMORY;<br />        T1</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000"> p </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> NULL;<br />        p </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000"> <strong>T1(pv);</strong><br />        </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> (p </span><span style="COLOR: #000000">!=</span><span style="COLOR: #000000"> NULL)<br />        {<br />            <strong>p</strong></span><span style="COLOR: #000000"><strong>-&gt;</strong></span><span style="COLOR: #000000"><strong>SetVoid(pv);</strong><br />            p</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">InternalFinalConstructAddRef();<br />            hRes </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> p</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">FinalConstruct();<br />            </span><span style="COLOR: #000000">p</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">InternalFinalConstructRelease();<br />            </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> (hRes </span><span style="COLOR: #000000">==</span><span style="COLOR: #000000"> S_OK)<br />                hRes </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> p</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">QueryInterface(riid, ppv);<br />            </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> (hRes </span><span style="COLOR: #000000">!=</span><span style="COLOR: #000000"> S_OK)<br />                delete p;<br />        }<br />        </span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000"> hRes;<br />    }<br />};</span></div><br />         “创建者”通过提供一个静态函数CreateInstance来创建指定类的实例，并且查询指定的接口。第一个参数在实例化普通对象和class factory对象时会有不同：对于普通对象，通常会传递聚合外部对象的IUnknown指针，如果是非聚合创建，可以传递NULL（详见ATL对COM实体身份的支持四）；稍后会介绍在class factory创建时第一个参数的用处。<br />         在ATL中，一个class factory对象只能创建一种类型的COM类实例。在class factory的CreateInstance函数中，它不是硬编码被创建的对象类型，而是通过一个<em><strong>函数指针</strong></em>成员变量来创建它所管理的对象，而这个函数指针指向的通常就是某个COM类的“创建者”类的CreateInstance静态函数的地址，此地址是在class factory对象被它自身的“创建者”的CreateInstance函数创建时通过第一个参数传进来的，class factory重新定义了SetVoid函数，并且保存这个地址：<br />          
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000"> CComClassFactory :<br />    </span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000"> IClassFactory,<br />    </span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000"> CComObjectRootEx</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">CComGlobalsThreadModel</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br />{<br /></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:<br />    </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> IClassFactory</span><span style="COLOR: #008000"><br /></span><span style="COLOR: #000000">    STDMETHOD(CreateInstance)(LPUNKNOWN pUnkOuter, REFIID riid, </span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">**</span><span style="COLOR: #000000"> ppvObj)<br />    {<br /></span><span style="COLOR: #000000">        HRESULT hRes </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> E_POINTER;<br />        </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> (ppvObj </span><span style="COLOR: #000000">!=</span><span style="COLOR: #000000"> NULL)<br />        {<br />            </span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">ppvObj </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> NULL;<br /></span><span style="COLOR: #000000">            </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> ((pUnkOuter </span><span style="COLOR: #000000">!=</span><span style="COLOR: #000000"> NULL) </span><span style="COLOR: #000000">&amp;&amp;</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">!</span><span style="COLOR: #000000">InlineIsEqualUnknown(riid))<br />            {<br /></span><span style="COLOR: #000000">                hRes </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> CLASS_E_NOAGGREGATION;<br />            }<br />            </span><span style="COLOR: #0000ff">else</span><span style="COLOR: #000000"><br />                hRes </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> m_pfnCreateInstance(pUnkOuter, riid, ppvObj);<br />        }<br />        </span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000"> hRes;<br />    }<br /><br />    STDMETHOD(LockServer)(BOOL fLock)<br />    {<br />        </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> (fLock)<br />            _pAtlModule</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">Lock();<br />        </span><span style="COLOR: #0000ff">else</span><span style="COLOR: #000000"><br />            _pAtlModule</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">Unlock();<br />        </span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000"> S_OK;<br />    }<br /> <br /></span><span style="COLOR: #000000">    </span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000"> SetVoid(</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000"> pv)<br />    {<br />        m_pfnCreateInstance </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> (_ATL_CREATORFUNC</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">)pv;<br />    }<br /><br />    _ATL_CREATORFUNC</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000"> m_pfnCreateInstance;<br />};</span></div><br />         根据上面的讨论，一个COM类的创建者会像这个样子：<br />         CComCreator&lt; CComObject&lt;CMyClass&gt; &gt;<br />         而一个class factory的创建者会像这个样子：<br />         CComCreator&lt; CComCachedObject&lt;CComClassFactory&gt; &gt;。<br />         <br />         ATL在客户请求创建CMyClass对象时执行的伪代码如下：<br />          
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #000000">typedef CComCreator</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000"> CComCachedObject</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">CComClassFactory</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"> CClassFactoryCreator;<br />typedef CComCreator</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000"> CComObject</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">CMyClass</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"> CMyClassCreator;<br /><br />IClassFactory</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000"> pcf</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">NULL;<br />CClassFactoryCreator::CreateInstance(</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">CMyClassCreator::CreateInstance,__uuidof(IClassFactory),</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">pcf);<br />pcf</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">CreateInstance(pOuter,__uuidof(IMyInterface),ppvObj);</span></div><img src ="http://www.cppblog.com/HeavenOnProg/aggbug/21605.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/HeavenOnProg/" target="_blank">michael</a> 2007-04-10 17:36 <a href="http://www.cppblog.com/HeavenOnProg/archive/2007/04/10/21605.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ATL对COM实体身份的支持（四）—— CComObject及其伙伴</title><link>http://www.cppblog.com/HeavenOnProg/archive/2007/04/06/21408.html</link><dc:creator>michael</dc:creator><author>michael</author><pubDate>Fri, 06 Apr 2007 07:33:00 GMT</pubDate><guid>http://www.cppblog.com/HeavenOnProg/archive/2007/04/06/21408.html</guid><wfw:comment>http://www.cppblog.com/HeavenOnProg/comments/21408.html</wfw:comment><comments>http://www.cppblog.com/HeavenOnProg/archive/2007/04/06/21408.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/HeavenOnProg/comments/commentRss/21408.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/HeavenOnProg/services/trackbacks/21408.html</trackback:ping><description><![CDATA[
		<p>
		</p>
		<p>      有了CComObjectRootBase、CComObjectRootEx和线程模型特征类这些基础原料，CComObject和它的伙伴们便可以自由的发挥它们的想象了。<br /><br />1.CComObject —— 普通堆对象      <br />   下面是精简的CComObject模板类的定义：      </p>
		<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee">
				<span style="COLOR: #000000">template </span>
				<span style="COLOR: #000000">&lt;</span>
				<span style="COLOR: #0000ff">class</span>
				<span style="COLOR: #000000"> Base</span>
				<span style="COLOR: #000000">&gt;</span>
				<span style="COLOR: #000000">
						<br />
				</span>
				<span style="COLOR: #0000ff">class</span>
				<span style="COLOR: #000000"> CComObject : </span>
				<span style="COLOR: #0000ff">public</span>
				<span style="COLOR: #000000"> Base<br />{<br /></span>
				<span style="COLOR: #0000ff">public</span>
				<span style="COLOR: #000000">:<br />    CComObject(</span>
				<span style="COLOR: #0000ff">void</span>
				<span style="COLOR: #000000">*</span>
				<span style="COLOR: #000000"> </span>
				<span style="COLOR: #000000">=</span>
				<span style="COLOR: #000000"> NULL) </span>
				<span style="COLOR: #0000ff">throw</span>
				<span style="COLOR: #000000">()<br />    {<br />        _pAtlModule</span>
				<span style="COLOR: #000000">-&gt;</span>
				<span style="COLOR: #000000">Lock();<br />    }<br />    <br /></span>
				<span style="COLOR: #0000ff">    virtual</span>
				<span style="COLOR: #000000"> </span>
				<span style="COLOR: #000000">~</span>
				<span style="COLOR: #000000">CComObject() </span>
				<span style="COLOR: #0000ff">throw</span>
				<span style="COLOR: #000000">()<br />    {<br /></span>
				<span style="COLOR: #000000">        FinalRelease();<br /></span>
				<span style="COLOR: #000000">        _pAtlModule</span>
				<span style="COLOR: #000000">-&gt;</span>
				<span style="COLOR: #000000">Unlock();<br />    }<br />    <br /></span>
				<span style="COLOR: #000000">    STDMETHOD_(ULONG, AddRef)() {</span>
				<span style="COLOR: #0000ff">return</span>
				<span style="COLOR: #000000"> InternalAddRef();}<br />    STDMETHOD_(ULONG, Release)()<br />    {<br />        ULONG l </span>
				<span style="COLOR: #000000">=</span>
				<span style="COLOR: #000000"> InternalRelease();<br />        </span>
				<span style="COLOR: #0000ff">if</span>
				<span style="COLOR: #000000"> (l </span>
				<span style="COLOR: #000000">==</span>
				<span style="COLOR: #000000"> </span>
				<span style="COLOR: #000000">0</span>
				<span style="COLOR: #000000">)<br />            delete </span>
				<span style="COLOR: #0000ff">this</span>
				<span style="COLOR: #000000">;<br />        </span>
				<span style="COLOR: #0000ff">return</span>
				<span style="COLOR: #000000"> l;<br />    }<br />    <br /></span>
				<span style="COLOR: #000000">    STDMETHOD(QueryInterface)(REFIID iid, </span>
				<span style="COLOR: #0000ff">void</span>
				<span style="COLOR: #000000"> </span>
				<span style="COLOR: #000000">**</span>
				<span style="COLOR: #000000"> ppvObject) </span>
				<span style="COLOR: #0000ff">throw</span>
				<span style="COLOR: #000000">()<br />    {</span>
				<span style="COLOR: #0000ff">return</span>
				<span style="COLOR: #000000"> _InternalQueryInterface(iid, ppvObject);}<br />    </span>
				<span style="COLOR: #000000">
						<br />    </span>
				<span style="COLOR: #0000ff">static</span>
				<span style="COLOR: #000000"> HRESULT WINAPI CreateInstance(CComObject</span>
				<span style="COLOR: #000000">&lt;</span>
				<span style="COLOR: #000000">Base</span>
				<span style="COLOR: #000000">&gt;**</span>
				<span style="COLOR: #000000"> pp) </span>
				<span style="COLOR: #0000ff">throw</span>
				<span style="COLOR: #000000">();<br />};</span>
		</div>
		<p>
				<br />“普通堆对象”是使用最为频繁的类，它有如下特征：<br />（1）在堆中分配内存 —— 计数归零时用delete销毁<br />（2）支持独立存在的对象 —— 使用InternalXXX来实现IUnknown功能<br />（3）产生时锁定服务器，销毁时解锁服务器 —— 适用于大多数COM对象</p>
		<p>2. CComAggObject —— 被聚合堆对象</p>
		<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee">
				<span style="COLOR: #000000">template </span>
				<span style="COLOR: #000000">&lt;</span>
				<span style="COLOR: #0000ff">class</span>
				<span style="COLOR: #000000"> contained</span>
				<span style="COLOR: #000000">&gt;</span>
				<span style="COLOR: #000000">
						<br />
				</span>
				<span style="COLOR: #0000ff">class</span>
				<span style="COLOR: #000000"> CComAggObject :<br />    </span>
				<span style="COLOR: #0000ff">public</span>
				<span style="COLOR: #000000"> IUnknown,<br />    </span>
				<span style="COLOR: #0000ff">public</span>
				<span style="COLOR: #000000"> CComObjectRootEx</span>
				<span style="COLOR: #000000">&lt;</span>
				<span style="COLOR: #000000"> typename contained::_ThreadModel::ThreadModelNoCS </span>
				<span style="COLOR: #000000">&gt;</span>
				<span style="COLOR: #000000">
						<br />{<br /></span>
				<span style="COLOR: #0000ff">public</span>
				<span style="COLOR: #000000">:<br />    CComAggObject(</span>
				<span style="COLOR: #0000ff">void</span>
				<span style="COLOR: #000000">*</span>
				<span style="COLOR: #000000"> pv) : m_contained(pv)<br />    {<br />        _pAtlModule</span>
				<span style="COLOR: #000000">-&gt;</span>
				<span style="COLOR: #000000">Lock();<br />    }<br />    </span>
				<span style="COLOR: #000000">HRESULT FinalConstruct()<br />    {<br />        CComObjectRootEx</span>
				<span style="COLOR: #000000">&lt;</span>
				<span style="COLOR: #000000">contained::_ThreadModel::ThreadModelNoCS</span>
				<span style="COLOR: #000000">&gt;</span>
				<span style="COLOR: #000000">::FinalConstruct();<br />        </span>
				<span style="COLOR: #0000ff">return</span>
				<span style="COLOR: #000000"> m_contained.FinalConstruct();<br />    }<br />    </span>
				<span style="COLOR: #0000ff">void</span>
				<span style="COLOR: #000000"> FinalRelease()<br />    {<br />        CComObjectRootEx</span>
				<span style="COLOR: #000000">&lt;</span>
				<span style="COLOR: #000000">contained::_ThreadModel::ThreadModelNoCS</span>
				<span style="COLOR: #000000">&gt;</span>
				<span style="COLOR: #000000">::FinalRelease();<br />        m_contained.FinalRelease();<br />    }<br />   </span>
				<span style="COLOR: #000000"> </span>
				<span style="COLOR: #0000ff">virtual</span>
				<span style="COLOR: #000000"> </span>
				<span style="COLOR: #000000">~</span>
				<span style="COLOR: #000000">CComAggObject()<br />    {<br />       </span>
				<span style="COLOR: #000000"> FinalRelease();<br /></span>
				<span style="COLOR: #000000">        _pAtlModule</span>
				<span style="COLOR: #000000">-&gt;</span>
				<span style="COLOR: #000000">Unlock();<br />    }<br /><br />    STDMETHOD_(ULONG, AddRef)() {</span>
				<span style="COLOR: #0000ff">return</span>
				<span style="COLOR: #000000"> InternalAddRef();}<br />    STDMETHOD_(ULONG, Release)()<br />    {<br />        ULONG l </span>
				<span style="COLOR: #000000">=</span>
				<span style="COLOR: #000000"> InternalRelease();<br />        </span>
				<span style="COLOR: #0000ff">if</span>
				<span style="COLOR: #000000"> (l </span>
				<span style="COLOR: #000000">==</span>
				<span style="COLOR: #000000"> </span>
				<span style="COLOR: #000000">0</span>
				<span style="COLOR: #000000">)<br />            delete </span>
				<span style="COLOR: #0000ff">this</span>
				<span style="COLOR: #000000">;<br />        </span>
				<span style="COLOR: #0000ff">return</span>
				<span style="COLOR: #000000"> l;<br />    }<br />    STDMETHOD(QueryInterface)(REFIID iid, </span>
				<span style="COLOR: #0000ff">void</span>
				<span style="COLOR: #000000"> </span>
				<span style="COLOR: #000000">**</span>
				<span style="COLOR: #000000"> ppvObject)<br />    {<br /></span>
				<span style="COLOR: #000000">        HRESULT hRes </span>
				<span style="COLOR: #000000">=</span>
				<span style="COLOR: #000000"> S_OK;<br />        </span>
				<span style="COLOR: #0000ff">if</span>
				<span style="COLOR: #000000"> (InlineIsEqualUnknown(iid))<br />        {<br />            </span>
				<span style="COLOR: #000000">*</span>
				<span style="COLOR: #000000">ppvObject </span>
				<span style="COLOR: #000000">=</span>
				<span style="COLOR: #000000"> (</span>
				<span style="COLOR: #0000ff">void</span>
				<span style="COLOR: #000000">*</span>
				<span style="COLOR: #000000">)(IUnknown</span>
				<span style="COLOR: #000000">*</span>
				<span style="COLOR: #000000">)</span>
				<span style="COLOR: #0000ff">this</span>
				<span style="COLOR: #000000">;<br />            AddRef();<br /></span>
				<span style="COLOR: #000000">        }<br />        </span>
				<span style="COLOR: #0000ff">else</span>
				<span style="COLOR: #000000">
						<br />            hRes </span>
				<span style="COLOR: #000000">=</span>
				<span style="COLOR: #000000"> m_contained._InternalQueryInterface(iid, ppvObject);<br />        </span>
				<span style="COLOR: #0000ff">return</span>
				<span style="COLOR: #000000"> hRes;<br />    }<br />   </span>
				<span style="COLOR: #000000"> </span>
				<span style="COLOR: #0000ff">static</span>
				<span style="COLOR: #000000"> HRESULT WINAPI CreateInstance(LPUNKNOWN pUnkOuter, CComAggObject</span>
				<span style="COLOR: #000000">&lt;</span>
				<span style="COLOR: #000000">contained</span>
				<span style="COLOR: #000000">&gt;**</span>
				<span style="COLOR: #000000"> pp)；<br /></span>
				<span style="COLOR: #000000">
						<br />    CComContainedObject</span>
				<span style="COLOR: #000000">&lt;</span>
				<span style="COLOR: #000000">contained</span>
				<span style="COLOR: #000000">&gt;</span>
				<span style="COLOR: #000000"> m_contained;<br />};</span>
		</div>
		<p>
				<br />  CComAggObject有如下特征：<br />（1）在堆中分配内存<br />（2）支持被聚合聚合的对象<br />           实现了两份IUnknown：CComAggObject实现了内部聚合类真正的IUnknown，它管理对象的生存期，并且完成接口查询（通过contained对象的_InternalQueryInterface）；contained对象实现了具有转发功能的IUnknown，它将所有的调用转发给CComAggObject在构造函数中收到的外部IUnknown指针。<br />（3）产生时锁定服务器，销毁时解锁服务器<br /><br />3. CComTearOffObject —— tear-off 对象</p>
		<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee">
				<span style="COLOR: #000000">template </span>
				<span style="COLOR: #000000">&lt;</span>
				<span style="COLOR: #0000ff">class</span>
				<span style="COLOR: #000000"> Base</span>
				<span style="COLOR: #000000">&gt;</span>
				<span style="COLOR: #000000">
						<br />
				</span>
				<span style="COLOR: #0000ff">class</span>
				<span style="COLOR: #000000"> CComTearOffObject : </span>
				<span style="COLOR: #0000ff">public</span>
				<span style="COLOR: #000000"> Base<br />{<br /></span>
				<span style="COLOR: #0000ff">public</span>
				<span style="COLOR: #000000">:<br />    CComTearOffObject(</span>
				<span style="COLOR: #0000ff">void</span>
				<span style="COLOR: #000000">*</span>
				<span style="COLOR: #000000"> pv)<br />    {<br /></span>
				<span style="COLOR: #000000">        m_pOwner </span>
				<span style="COLOR: #000000">=</span>
				<span style="COLOR: #000000"> reinterpret_cast</span>
				<span style="COLOR: #000000">&lt;</span>
				<span style="COLOR: #000000">Base::_OwnerClass</span>
				<span style="COLOR: #000000">*&gt;</span>
				<span style="COLOR: #000000">(pv);<br />        m_pOwner</span>
				<span style="COLOR: #000000">-&gt;</span>
				<span style="COLOR: #000000">AddRef();<br />    }<br /></span>
				<span style="COLOR: #000000">    </span>
				<span style="COLOR: #000000">~</span>
				<span style="COLOR: #000000">CComTearOffObject()<br />    {<br /></span>
				<span style="COLOR: #000000">        FinalRelease();<br /></span>
				<span style="COLOR: #000000">        m_pOwner</span>
				<span style="COLOR: #000000">-&gt;</span>
				<span style="COLOR: #000000">Release();<br />    }<br /><br />    STDMETHOD_(ULONG, AddRef)() </span>
				<span style="COLOR: #0000ff">throw</span>
				<span style="COLOR: #000000">() {</span>
				<span style="COLOR: #0000ff">return</span>
				<span style="COLOR: #000000"> InternalAddRef();}<br />    STDMETHOD_(ULONG, Release)() </span>
				<span style="COLOR: #0000ff">throw</span>
				<span style="COLOR: #000000">()<br />    {<br />        ULONG l </span>
				<span style="COLOR: #000000">=</span>
				<span style="COLOR: #000000"> InternalRelease();<br />        </span>
				<span style="COLOR: #0000ff">if</span>
				<span style="COLOR: #000000"> (l </span>
				<span style="COLOR: #000000">==</span>
				<span style="COLOR: #000000"> </span>
				<span style="COLOR: #000000">0</span>
				<span style="COLOR: #000000">)<br />            delete </span>
				<span style="COLOR: #0000ff">this</span>
				<span style="COLOR: #000000">;<br />        </span>
				<span style="COLOR: #0000ff">return</span>
				<span style="COLOR: #000000"> l;<br />    }<br />    STDMETHOD(QueryInterface)(REFIID iid, </span>
				<span style="COLOR: #0000ff">void</span>
				<span style="COLOR: #000000"> </span>
				<span style="COLOR: #000000">**</span>
				<span style="COLOR: #000000"> ppvObject) </span>
				<span style="COLOR: #0000ff">throw</span>
				<span style="COLOR: #000000">()<br />    {<br />        </span>
				<span style="COLOR: #0000ff">return</span>
				<span style="COLOR: #000000"> m_pOwner</span>
				<span style="COLOR: #000000">-&gt;</span>
				<span style="COLOR: #000000">QueryInterface(iid, ppvObject);<br />    }<br />};</span>
		</div>
		<br />   tear-off对象有如下特征：<br />（1）在堆中分配内存<br />（2）支持在ATL组件内部使用的tear-off技术<br />（3）生成时锁定父对象，销毁时解锁父对象<br />（4）生命周期由自己管理，接口查询委托父对象<br /><br />4. CComObjectStack —— 栈对象<br />    
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #000000">template </span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000"> Base</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br /></span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000"> CComObjectStackEx : </span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000"> Base<br />{<br /></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:<br />    CComObjectStackEx(</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> NULL) <br />    { <br /></span><span style="COLOR: #000000">        m_hResFinalConstruct </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> FinalConstruct(); <br />    }<br />    </span><span style="COLOR: #0000ff">virtual</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">~</span><span style="COLOR: #000000">CComObjectStackEx()<br />    {<br />        </span><span style="COLOR: #000000">FinalRelease();<br /></span><span style="COLOR: #000000">    }<br /><br />    STDMETHOD_(ULONG, AddRef)()<br />    {<br /></span><span style="COLOR: #0000ff">        return</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br /></span><span style="COLOR: #000000">    }<br /><br />    STDMETHOD_(ULONG, Release)()<br />    {<br /></span><span style="COLOR: #000000">        </span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br /></span><span style="COLOR: #000000">    }<br /><br />    STDMETHOD(QueryInterface)(REFIID iid, </span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">**</span><span style="COLOR: #000000"> ppvObject)<br />    {<br />        </span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000"> _InternalQueryInterface(iid, ppvObject);<br />    }<br /><br />    HRESULT m_hResFinalConstruct;<br />};<br /></span></div><br />   栈对象有如下特征：<br />（1）内存分配于栈上 —— 不需要对象考虑释放问题<br />（2）无引用计数功能<br />（3）构造时初始化 —— 需要在构造函数调用后检查m_hResFinalConstruct，以判断对象是否构造成功<br />（4）不锁定服务器<br /><br />5. CComObjectGlobal —— 全局对象<br /><div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #000000">template </span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000"> Base</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br /></span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000"> CComObjectGlobal : </span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000"> Base<br />{<br /></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:<br />    CComObjectGlobal(</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> NULL)<br />    {<br />        </span><span style="COLOR: #000000">m_hResFinalConstruct </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> FinalConstruct();<br />    }<br />    </span><span style="COLOR: #0000ff">virtual</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">~</span><span style="COLOR: #000000">CComObjectGlobal()<br />    {<br />             FinalRelease();<br />  </span><span style="COLOR: #000000">  }<br />    STDMETHOD_(ULONG, AddRef)() </span><span style="COLOR: #0000ff">throw</span><span style="COLOR: #000000">()<br />    {<br />        </span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000"> _pAtlModule</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">Lock();<br />    }<br />    STDMETHOD_(ULONG, Release)() </span><span style="COLOR: #0000ff">throw</span><span style="COLOR: #000000">()<br />    {<br />        </span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000"> _pAtlModule</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">Unlock();<br />    }<br />    STDMETHOD(QueryInterface)(REFIID iid, </span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">**</span><span style="COLOR: #000000"> ppvObject) </span><span style="COLOR: #0000ff">throw</span><span style="COLOR: #000000">()<br />    {<br />        </span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000"> _InternalQueryInterface(iid, ppvObject);<br />    }<br />    HRESULT m_hResFinalConstruct;<br />};</span></div>   <br />   全局对象有如下特征：<br />（1）在全局数据区分配内存<br />（2）初始化时不锁定服务器，引用计数变化时才锁定或者解锁服务器，这使得全局对象可以被用于全局类厂对象，以解决服务器和类厂之间的死锁问题<br />（3）构造方式同栈对象<br /><br />   还有一些其它种类的生存期管理类，如CComObjectNoLock、CComObjectCached、CComPolyObject等等，它们也都有自己独到的用处，我们也可以根据自己的需要编写自定义的类。总之CComObjectRootBase、CComObjectRootEx和线程模型特征类就像是积木一样，我们可以任意的把它们组合成想要的形状。<img src ="http://www.cppblog.com/HeavenOnProg/aggbug/21408.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/HeavenOnProg/" target="_blank">michael</a> 2007-04-06 15:33 <a href="http://www.cppblog.com/HeavenOnProg/archive/2007/04/06/21408.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ATL对COM实体身份的支持（三）—— 访问同步支持</title><link>http://www.cppblog.com/HeavenOnProg/archive/2007/04/06/21403.html</link><dc:creator>michael</dc:creator><author>michael</author><pubDate>Fri, 06 Apr 2007 06:39:00 GMT</pubDate><guid>http://www.cppblog.com/HeavenOnProg/archive/2007/04/06/21403.html</guid><wfw:comment>http://www.cppblog.com/HeavenOnProg/comments/21403.html</wfw:comment><comments>http://www.cppblog.com/HeavenOnProg/archive/2007/04/06/21403.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/HeavenOnProg/comments/commentRss/21403.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/HeavenOnProg/services/trackbacks/21403.html</trackback:ping><description><![CDATA[1.CComSingleThreadModel和CComMultiThreadModel特征类：<br /><div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000"> CComSingleThreadModel<br />{<br /></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:<br />    </span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000"> ULONG WINAPI Increment(LPLONG p) </span><span style="COLOR: #0000ff">throw</span><span style="COLOR: #000000">() {</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">++</span><span style="COLOR: #000000">(</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">p);}<br />    </span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000"> ULONG WINAPI Decrement(LPLONG p) </span><span style="COLOR: #0000ff">throw</span><span style="COLOR: #000000">() {</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">--</span><span style="COLOR: #000000">(</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">p);}<br />    typedef CComFakeCriticalSection AutoCriticalSection;<br />    typedef CComFakeCriticalSection CriticalSection;<br />    typedef CComSingleThreadModel ThreadModelNoCS;<br />};</span></div><div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000"> CComMultiThreadModel<br />{<br /></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:<br />    </span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000"> ULONG WINAPI Increment(LPLONG p) </span><span style="COLOR: #0000ff">throw</span><span style="COLOR: #000000">() {</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000"> InterlockedIncrement(p);}<br />    </span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000"> ULONG WINAPI Decrement(LPLONG p) </span><span style="COLOR: #0000ff">throw</span><span style="COLOR: #000000">() {</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000"> InterlockedDecrement(p);}<br />    typedef CComAutoCriticalSection AutoCriticalSection;<br />    typedef CComCriticalSection CriticalSection;<br />    typedef CComMultiThreadModelNoCS ThreadModelNoCS;<br />};</span></div>其中的CFakeCriticalSection定义如下：<br /><div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000"> CComFakeCriticalSection<br />{<br /></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:<br />    HRESULT Lock() </span><span style="COLOR: #0000ff">throw</span><span style="COLOR: #000000">() { </span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000"> S_OK; }<br />    HRESULT Unlock() </span><span style="COLOR: #0000ff">throw</span><span style="COLOR: #000000">() { </span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000"> S_OK; }<br />    HRESULT Init() </span><span style="COLOR: #0000ff">throw</span><span style="COLOR: #000000">() { </span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000"> S_OK; }<br />    HRESULT Term() </span><span style="COLOR: #0000ff">throw</span><span style="COLOR: #000000">() { </span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000"> S_OK; }<br />};</span></div><br />这两个类提供了针对特定套间对象的同步控制支持。<br />CComSingleThreadModel适用于单线程套间对象，它不采用任何线程同步机制；CComMultiThreadModel适用于多线程套间对象，它使用win32的同步机制来实现。<br /><br />2.CComObjectRootEx模板类<br /><div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #000000">template </span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000"> ThreadModel</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br /></span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000"> CComObjectRootEx : </span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000"> CComObjectRootBase<br />{<br /></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:<br />    typedef ThreadModel _ThreadModel;<br />    typedef typename _ThreadModel::AutoCriticalSection _CritSec;<br />    typedef CComObjectLockT</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">_ThreadModel</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"> ObjectLock;<br /><br />    ULONG InternalAddRef()<br />    {<br />       </span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000"> _ThreadModel::Increment(</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">m_dwRef);<br />    }<br />    ULONG InternalRelease()<br />    {<br /></span><span style="COLOR: #000000">        </span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000"> _ThreadModel::Decrement(</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">m_dwRef);<br /></span><span style="COLOR: #000000">    }<br /><br />    </span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000"> Lock() {m_critsec.Lock();}<br />    </span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000"> Unlock() {m_critsec.Unlock();}<br /><br /></span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000">:<br />    _CritSec m_critsec;<br />};</span></div><br />它使用传入的线程模型特征类来实现对象独立存在时所需要的引用计数支持，同时提供了一个方便对象开发使用的同步锁，我们可以使用这个锁来完成对自定义数据访问的保护。<img src ="http://www.cppblog.com/HeavenOnProg/aggbug/21403.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/HeavenOnProg/" target="_blank">michael</a> 2007-04-06 14:39 <a href="http://www.cppblog.com/HeavenOnProg/archive/2007/04/06/21403.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ATL对COM实体身份的支持（二）—— CComObjectRootBase</title><link>http://www.cppblog.com/HeavenOnProg/archive/2007/04/06/21393.html</link><dc:creator>michael</dc:creator><author>michael</author><pubDate>Fri, 06 Apr 2007 05:51:00 GMT</pubDate><guid>http://www.cppblog.com/HeavenOnProg/archive/2007/04/06/21393.html</guid><wfw:comment>http://www.cppblog.com/HeavenOnProg/comments/21393.html</wfw:comment><comments>http://www.cppblog.com/HeavenOnProg/archive/2007/04/06/21393.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/HeavenOnProg/comments/commentRss/21393.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/HeavenOnProg/services/trackbacks/21393.html</trackback:ping><description><![CDATA[
		<p>下面是CComObjectRootBase的关键代码：</p>
		<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee">
				<span style="COLOR: #0000ff">class</span>
				<span style="COLOR: #000000"> CComObjectRootBase<br />{<br /></span>
				<span style="COLOR: #0000ff">public</span>
				<span style="COLOR: #000000">:<br />     // 构造支持<br />     //<br />  </span> <span style="COLOR: #000000">  HRESULT FinalConstruct();<br /></span><span style="COLOR: #000000">   </span>  <span style="COLOR: #0000ff">void</span><span style="COLOR: #000000"> FinalRelease(); <br /><br />     //  接口查询支持<br /></span><span style="COLOR: #000000">     //<br /></span><span style="COLOR: #000000">     </span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000"> HRESULT WINAPI InternalQueryInterface(</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000"> pThis,<br />        </span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000"> _ATL_INTMAP_ENTRY</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000"> pEntries, REFIID iid, </span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">**</span><span style="COLOR: #000000"> ppvObject);<br />   <br /><span style="COLOR: #0000ff">    static</span><span style="COLOR: #000000"> HRESULT WINAPI _Break(</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">, REFIID iid, </span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">**</span><font style="BACKGROUND-COLOR: #eeeeee"> </font><span style="COLOR: #000000"> </span><span style="COLOR: #000000">, DWORD_PTR </span><span style="COLOR: #000000">);<br /></span><span style="COLOR: #000000">    </span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000"> HRESULT WINAPI _NoInterface(</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">*</span><font style="BACKGROUND-COLOR: #eeeeee"> </font><span style="COLOR: #000000"> </span><span style="COLOR: #000000">, REFIID </span><span style="COLOR: #000000">, </span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">**</span><font style="BACKGROUND-COLOR: #eeeeee"> </font><span style="COLOR: #000000"> </span><span style="COLOR: #000000">, DWORD_PTR </span><span style="COLOR: #000000">);<br /></span><span style="COLOR: #000000">    </span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000"> HRESULT WINAPI _Creator(</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000"> pv, REFIID iid, </span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">**</span><span style="COLOR: #000000">ppvObject, DWORD_PTR dw);<br /></span><span style="COLOR: #000000">    </span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000"> HRESULT WINAPI _Delegate(</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000"> pv, REFIID iid, </span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">**</span><span style="COLOR: #000000"> ppvObject, DWORD_PTR dw);<br />   </span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000"> HRESULT WINAPI _Chain(</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000"> pv, REFIID iid, </span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">**</span><span style="COLOR: #000000"> ppvObject, DWORD_PTR dw);<br />    </span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000"> HRESULT WINAPI _ChainAttr(</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000"> pv, REFIID iid, </span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">**</span><span style="COLOR: #000000"> ppvObject, DWORD_PTR dw);<br />   </span><font style="BACKGROUND-COLOR: #eeeeee"> </font><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000"> HRESULT WINAPI _Cache(</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000"> pv, REFIID iid, </span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">**</span><span style="COLOR: #000000"> ppvObject, DWORD_PTR dw);<br /><br />    //  聚合支持<br />    //<br /></span> </span> <span style="COLOR: #000000">  ULONG OuterAddRef()<br />    {<br />        </span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000"> m_pOuterUnknown</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">AddRef();<br />    }<br />    ULONG OuterRelease()<br />    {<br />        </span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000"> m_pOuterUnknown</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">Release();<br />    }<br />    HRESULT OuterQueryInterface(REFIID iid, </span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">**</span><span style="COLOR: #000000"> ppvObject)<br />    {<br />        </span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000"> m_pOuterUnknown</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">QueryInterface(iid, ppvObject);<br />    }<br />    <br /></span><span style="COLOR: #000000">    // 实体身份支持<br />    //<br />    union<br />    {<br />        </span><span style="COLOR: #0000ff">long</span><span style="COLOR: #000000"> m_dwRef;<br />         IUnknown</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000"> m_pOuterUnknown;<br />    };<br />};</span></div>
		<br />CComObjectRootBase主要功能分为：<br />（1）构造支持：<br />            即FinalConstruct和FinalRelease，它们用于安全的构造和销毁对象。<br />（2）接口查询支持<br />            通过接口映射表来完成接口查询功能，详细内容见后面的文章。<br />（3）聚合状态下引用计数操作的支持<br />            提供了将IUnknown请求委托给外部组件的支持。当对象独立存在时，对引用计数操作的支持被放置于CComObjectRootEx中，因为涉及到了套间和访问同步。<br />（4）实体身份支持<br />            使得对象可以独立存在或者被聚合，因为运行时刻对象只能以一种方式存在，所以使用了union。<img src ="http://www.cppblog.com/HeavenOnProg/aggbug/21393.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/HeavenOnProg/" target="_blank">michael</a> 2007-04-06 13:51 <a href="http://www.cppblog.com/HeavenOnProg/archive/2007/04/06/21393.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ATL对COM实体身份的支持（一）—— 类层次结构</title><link>http://www.cppblog.com/HeavenOnProg/archive/2007/04/06/21382.html</link><dc:creator>michael</dc:creator><author>michael</author><pubDate>Fri, 06 Apr 2007 03:46:00 GMT</pubDate><guid>http://www.cppblog.com/HeavenOnProg/archive/2007/04/06/21382.html</guid><wfw:comment>http://www.cppblog.com/HeavenOnProg/comments/21382.html</wfw:comment><comments>http://www.cppblog.com/HeavenOnProg/archive/2007/04/06/21382.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/HeavenOnProg/comments/commentRss/21382.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/HeavenOnProg/services/trackbacks/21382.html</trackback:ping><description><![CDATA[
		<img height="325" alt="ATLComClasses.JPG" src="http://www.cppblog.com/images/cppblog_com/heavenonprog/ATLComClasses.JPG" width="568" border="0" />
		<br />            一个COM对象必须实现IUnknown接口所规定的功能，即生命期管理和运行时类型转换。<br />（1）基本IUnknow功能<br />            对象的生存方式可以是堆存储、栈存储以及全局存储，同时COM还提供了一种被聚合的生存方式。生存方式不同，AddRef、Release和QueryInterface的实现方式就不同。比如：对于堆方式，Release要在引用计数归零时负责释放堆空间，而栈以及全局方式则不必；对于聚合方式，AddRef、Release以及大部分的QueryInterface调用要委托给外部对象。<br />            为了达到对象的逻辑功能与其生存方式的分离，COM把对IUnknown基本功能的实现推迟到类层次结构的最底层，即CComObject（或它的其他伙伴）处。<br />            CComObjectRootBase为CComObject的实现提供原材料的支持，如提供引用计数变量、基本的接口查询机制等，它是一个“功能集中类”。<br />（2）套间安全支持<br />            根据对象所处的套间类型，对象功能的实现需要不同的同步支持。对于单线程套间对象，由COM库来保证访问的同步；而对于多线程套间对象，需要自己来同步调用。为了使套间安全支持与逻辑功能分离，ATL提供了一组提供线程安全操作支持的特征类（traits类）—— CComSingleThreadModel及其伙伴。它们提供了对一个LONG变量“恰好线程安全”的增减操作，以及跟套间类型匹配的CriticalSection功能类。<br />            ATL同时提供了CComObjectRootEx模板类，它以某种ThreadModel特征类作为参数，提供对引用计数“恰好线程安全”的操作，并且提供了一个用于对象同步的锁。<br />            PS:“恰好线程安全”的操作的意思是：对于需要线程同步的对象，提供win32 CriticalSection支持；对于不需要的对象，则什么也不做。<br /><img src ="http://www.cppblog.com/HeavenOnProg/aggbug/21382.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/HeavenOnProg/" target="_blank">michael</a> 2007-04-06 11:46 <a href="http://www.cppblog.com/HeavenOnProg/archive/2007/04/06/21382.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>