??????有了CComObjectRootBase、CComObjectRootEx和線程模型特征類這些基礎原料,CComObject和它的伙伴們便可以自由的發揮它們的想象了。
1.CComObject —— 普通堆對象??????
???下面是精簡的CComObject模板類的定義:??????
template?
<
class
?Base
>
class ?CComObject?:? public ?Base
{
public :
????CComObject( void * ? = ?NULL)? throw ()
????{
????????_pAtlModule -> Lock();
????}
????
????virtual ? ~ CComObject()? throw ()
????{
????????FinalRelease();
??????? _pAtlModule -> Unlock();
????}
????
??? STDMETHOD_(ULONG,?AddRef)()?{ return ?InternalAddRef();}
????STDMETHOD_(ULONG,?Release)()
????{
????????ULONG?l? = ?InternalRelease();
???????? if ?(l? == ? 0 )
????????????delete? this ;
???????? return ?l;
????}
????
????STDMETHOD(QueryInterface)(REFIID?iid,? void ? ** ?ppvObject)? throw ()
????{ return ?_InternalQueryInterface(iid,?ppvObject);}
????
???? static ?HRESULT?WINAPI?CreateInstance(CComObject < Base >** ?pp)? throw ();
};
class ?CComObject?:? public ?Base
{
public :
????CComObject( void * ? = ?NULL)? throw ()
????{
????????_pAtlModule -> Lock();
????}
????
????virtual ? ~ CComObject()? throw ()
????{
????????FinalRelease();
??????? _pAtlModule -> Unlock();
????}
????
??? STDMETHOD_(ULONG,?AddRef)()?{ return ?InternalAddRef();}
????STDMETHOD_(ULONG,?Release)()
????{
????????ULONG?l? = ?InternalRelease();
???????? if ?(l? == ? 0 )
????????????delete? this ;
???????? return ?l;
????}
????
????STDMETHOD(QueryInterface)(REFIID?iid,? void ? ** ?ppvObject)? throw ()
????{ return ?_InternalQueryInterface(iid,?ppvObject);}
????
???? static ?HRESULT?WINAPI?CreateInstance(CComObject < Base >** ?pp)? throw ();
};
“普通堆對象”是使用最為頻繁的類,它有如下特征:
(1)在堆中分配內存 —— 計數歸零時用delete銷毀
(2)支持獨立存在的對象 —— 使用InternalXXX來實現IUnknown功能
(3)產生時鎖定服務器,銷毀時解鎖服務器 —— 適用于大多數COM對象
2. CComAggObject —— 被聚合堆對象
template?
<
class
?contained
>
class ?CComAggObject?:
???? public ?IUnknown,
???? public ?CComObjectRootEx < ?typename?contained::_ThreadModel::ThreadModelNoCS? >
{
public :
????CComAggObject( void * ?pv)?:?m_contained(pv)
????{
????????_pAtlModule -> Lock();
????}
???? HRESULT?FinalConstruct()
????{
????????CComObjectRootEx < contained::_ThreadModel::ThreadModelNoCS > ::FinalConstruct();
???????? return ?m_contained.FinalConstruct();
????}
???? void ?FinalRelease()
????{
????????CComObjectRootEx < contained::_ThreadModel::ThreadModelNoCS > ::FinalRelease();
????????m_contained.FinalRelease();
????}
??? ? virtual ? ~ CComAggObject()
????{
??????? ?FinalRelease();
????????_pAtlModule -> Unlock();
????}
????STDMETHOD_(ULONG,?AddRef)()?{ return ?InternalAddRef();}
????STDMETHOD_(ULONG,?Release)()
????{
????????ULONG?l? = ?InternalRelease();
???????? if ?(l? == ? 0 )
????????????delete? this ;
???????? return ?l;
????}
????STDMETHOD(QueryInterface)(REFIID?iid,? void ? ** ?ppvObject)
????{
????????HRESULT?hRes? = ?S_OK;
???????? if ?(InlineIsEqualUnknown(iid))
????????{
???????????? * ppvObject? = ?( void * )(IUnknown * ) this ;
????????????AddRef();
????????}
???????? else
????????????hRes? = ?m_contained._InternalQueryInterface(iid,?ppvObject);
???????? return ?hRes;
????}
??? ? static ?HRESULT?WINAPI?CreateInstance(LPUNKNOWN?pUnkOuter,?CComAggObject < contained >** ?pp);
????CComContainedObject < contained > ?m_contained;
};
class ?CComAggObject?:
???? public ?IUnknown,
???? public ?CComObjectRootEx < ?typename?contained::_ThreadModel::ThreadModelNoCS? >
{
public :
????CComAggObject( void * ?pv)?:?m_contained(pv)
????{
????????_pAtlModule -> Lock();
????}
???? HRESULT?FinalConstruct()
????{
????????CComObjectRootEx < contained::_ThreadModel::ThreadModelNoCS > ::FinalConstruct();
???????? return ?m_contained.FinalConstruct();
????}
???? void ?FinalRelease()
????{
????????CComObjectRootEx < contained::_ThreadModel::ThreadModelNoCS > ::FinalRelease();
????????m_contained.FinalRelease();
????}
??? ? virtual ? ~ CComAggObject()
????{
??????? ?FinalRelease();
????????_pAtlModule -> Unlock();
????}
????STDMETHOD_(ULONG,?AddRef)()?{ return ?InternalAddRef();}
????STDMETHOD_(ULONG,?Release)()
????{
????????ULONG?l? = ?InternalRelease();
???????? if ?(l? == ? 0 )
????????????delete? this ;
???????? return ?l;
????}
????STDMETHOD(QueryInterface)(REFIID?iid,? void ? ** ?ppvObject)
????{
????????HRESULT?hRes? = ?S_OK;
???????? if ?(InlineIsEqualUnknown(iid))
????????{
???????????? * ppvObject? = ?( void * )(IUnknown * ) this ;
????????????AddRef();
????????}
???????? else
????????????hRes? = ?m_contained._InternalQueryInterface(iid,?ppvObject);
???????? return ?hRes;
????}
??? ? static ?HRESULT?WINAPI?CreateInstance(LPUNKNOWN?pUnkOuter,?CComAggObject < contained >** ?pp);
????CComContainedObject < contained > ?m_contained;
};
? CComAggObject有如下特征:
(1)在堆中分配內存
(2)支持被聚合聚合的對象
???????????實現了兩份IUnknown:CComAggObject實現了內部聚合類真正的IUnknown,它管理對象的生存期,并且完成接口查詢(通過contained對象的_InternalQueryInterface);contained對象實現了具有轉發功能的IUnknown,它將所有的調用轉發給CComAggObject在構造函數中收到的外部IUnknown指針。
(3)產生時鎖定服務器,銷毀時解鎖服務器
3. CComTearOffObject —— tear-off 對象
template?
<
class
?Base
>
class ?CComTearOffObject?:? public ?Base
{
public :
????CComTearOffObject( void * ?pv)
????{
????????m_pOwner? = ?reinterpret_cast < Base::_OwnerClass *> (pv);
????????m_pOwner -> AddRef();
????}
???? ~ CComTearOffObject()
????{
????????FinalRelease();
????????m_pOwner -> Release();
????}
????STDMETHOD_(ULONG,?AddRef)()? throw ()?{ return ?InternalAddRef();}
????STDMETHOD_(ULONG,?Release)()? throw ()
????{
????????ULONG?l? = ?InternalRelease();
???????? if ?(l? == ? 0 )
????????????delete? this ;
???????? return ?l;
????}
????STDMETHOD(QueryInterface)(REFIID?iid,? void ? ** ?ppvObject)? throw ()
????{
???????? return ?m_pOwner -> QueryInterface(iid,?ppvObject);
????}
};
class ?CComTearOffObject?:? public ?Base
{
public :
????CComTearOffObject( void * ?pv)
????{
????????m_pOwner? = ?reinterpret_cast < Base::_OwnerClass *> (pv);
????????m_pOwner -> AddRef();
????}
???? ~ CComTearOffObject()
????{
????????FinalRelease();
????????m_pOwner -> Release();
????}
????STDMETHOD_(ULONG,?AddRef)()? throw ()?{ return ?InternalAddRef();}
????STDMETHOD_(ULONG,?Release)()? throw ()
????{
????????ULONG?l? = ?InternalRelease();
???????? if ?(l? == ? 0 )
????????????delete? this ;
???????? return ?l;
????}
????STDMETHOD(QueryInterface)(REFIID?iid,? void ? ** ?ppvObject)? throw ()
????{
???????? return ?m_pOwner -> QueryInterface(iid,?ppvObject);
????}
};
???tear-off對象有如下特征:
(1)在堆中分配內存
(2)支持在ATL組件內部使用的tear-off技術
(3)生成時鎖定父對象,銷毀時解鎖父對象
(4)生命周期由自己管理,接口查詢委托父對象
4. CComObjectStack —— 棧對象
???
template?<class?Base>
class?CComObjectStackEx?:?public?Base
{
public:
????CComObjectStackEx(void*?=?NULL)?
????{?
????????m_hResFinalConstruct?=?FinalConstruct();?
????}
????virtual?~CComObjectStackEx()
????{
??????? FinalRelease();
??? }
????STDMETHOD_(ULONG,?AddRef)()
????{
??????? return?0;
????}
????STDMETHOD_(ULONG,?Release)()
????{
????????return?0;
????}
????STDMETHOD(QueryInterface)(REFIID?iid,?void?**?ppvObject)
????{
????????return?_InternalQueryInterface(iid,?ppvObject);
????}
????HRESULT?m_hResFinalConstruct;
};
class?CComObjectStackEx?:?public?Base
{
public:
????CComObjectStackEx(void*?=?NULL)?
????{?
????????m_hResFinalConstruct?=?FinalConstruct();?
????}
????virtual?~CComObjectStackEx()
????{
??????? FinalRelease();
??? }
????STDMETHOD_(ULONG,?AddRef)()
????{
??????? return?0;
????}
????STDMETHOD_(ULONG,?Release)()
????{
????????return?0;
????}
????STDMETHOD(QueryInterface)(REFIID?iid,?void?**?ppvObject)
????{
????????return?_InternalQueryInterface(iid,?ppvObject);
????}
????HRESULT?m_hResFinalConstruct;
};
???棧對象有如下特征:
(1)內存分配于棧上 —— 不需要對象考慮釋放問題
(2)無引用計數功能
(3)構造時初始化 —— 需要在構造函數調用后檢查m_hResFinalConstruct,以判斷對象是否構造成功
(4)不鎖定服務器
5. CComObjectGlobal —— 全局對象
template?<class?Base>
class?CComObjectGlobal?:?public?Base
{
public:
????CComObjectGlobal(void*?=?NULL)
????{
??????? m_hResFinalConstruct?=?FinalConstruct();
????}
????virtual?~CComObjectGlobal()
????{
?????????????FinalRelease();
????}
????STDMETHOD_(ULONG,?AddRef)()?throw()
????{
????????return?_pAtlModule->Lock();
????}
????STDMETHOD_(ULONG,?Release)()?throw()
????{
????????return?_pAtlModule->Unlock();
????}
????STDMETHOD(QueryInterface)(REFIID?iid,?void?**?ppvObject)?throw()
????{
????????return?_InternalQueryInterface(iid,?ppvObject);
????}
????HRESULT?m_hResFinalConstruct;
};
???class?CComObjectGlobal?:?public?Base
{
public:
????CComObjectGlobal(void*?=?NULL)
????{
??????? m_hResFinalConstruct?=?FinalConstruct();
????}
????virtual?~CComObjectGlobal()
????{
?????????????FinalRelease();
????}
????STDMETHOD_(ULONG,?AddRef)()?throw()
????{
????????return?_pAtlModule->Lock();
????}
????STDMETHOD_(ULONG,?Release)()?throw()
????{
????????return?_pAtlModule->Unlock();
????}
????STDMETHOD(QueryInterface)(REFIID?iid,?void?**?ppvObject)?throw()
????{
????????return?_InternalQueryInterface(iid,?ppvObject);
????}
????HRESULT?m_hResFinalConstruct;
};
???全局對象有如下特征:
(1)在全局數據區分配內存
(2)初始化時不鎖定服務器,引用計數變化時才鎖定或者解鎖服務器,這使得全局對象可以被用于全局類廠對象,以解決服務器和類廠之間的死鎖問題
(3)構造方式同棧對象
???還有一些其它種類的生存期管理類,如CComObjectNoLock、CComObjectCached、CComPolyObject等等,它們也都有自己獨到的用處,我們也可以根據自己的需要編寫自定義的類。總之CComObjectRootBase、CComObjectRootEx和線程模型特征類就像是積木一樣,我們可以任意的把它們組合成想要的形狀。