自己的类从 CComObjectRoot ,CComCoClass派生, CComObject又从自己写的类派生
CComModel类模块的中心类,不区分进程内和本地组件。如果是本地组件则必须建立一个CComModule子类。
本地组件在引用计数为0时需要退出。
CComObjectRoot/CComObjectRootEx,任何ATL Com组件都必须从此类继承。想起IUnknown,而且支持对聚合的支持。
CComObjectRootEx是类模版,取一个参数:线程模型。
CComObjectRoot是默认服务器线程模型上参数化的CComObjectRootEx模版的类型定义。
CComCoCalss是任何ATL Com组件都必须继承的类,负责定义类厂。它定义宏DECLARE_CLASSFACTORY宏使用的
类厂模型。参数:类名和组件的CLSID。
CComObject用于实现IUnknown,其中AddRef和Release委托给CComObjectRoot。
FTM自由线程列集的支持
CComModule类ATL应用中心模块类CComModule,和MFC的CWinApp作用类似。使用对象映象表的全局表。
注册和反注册、用类厂初始化对象、建立客户和组件的根对象之间的通信、执行类厂的生命周期控制。
有了CComObjectRootBase、CComObjectRootEx和线程模型特征类这些基础原料,CComObject和它的伙伴们便可以自由的发挥它们的想象了。
1.CComObject —— 普通堆对象
下面是精简的CComObject模板类的定义:
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 —— 被聚合堆对象
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 对象
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 —— 栈对象
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 —— 全局对象
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和线程模型特征类就像是积木一样,我们可以任意的把它们组合成想要的形状。