随笔-6  评论-0  文章-16  trackbacks-0

      有了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和线程模型特征类就像是积木一样,我们可以任意的把它们组合成想要的形状。
posted on 2007-04-06 15:33 michael 阅读(3642) 评论(0)  编辑 收藏 引用 所属分类: 心得

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理