ATL 类的理解

自己的类从 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模板类的定义:      

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 ();
};


“普通堆对象”是使用最为频繁的类,它有如下特征:
(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;
};


   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);
     }
};

    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;
};

    栈对象有如下特征:
(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;
};
   
    全局对象有如下特征:
(1)在全局数据区分配内存
(2)初始化时不锁定服务器,引用计数变化时才锁定或者解锁服务器,这使得全局对象可以被用于全局类厂对象,以解决服务器和类厂之间的死锁问题
(3)构造方式同栈对象

    还有一些其它种类的生存期管理类,如CComObjectNoLock、CComObjectCached、CComPolyObject等等,它们也都有自己独到的用处,我们也可以根据自己的需要编写自定义的类。总之CComObjectRootBase、CComObjectRootEx和线程模型特征类就像是积木一样,我们可以任意的把它们组合成想要的形状。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值