组件聚合

对于HRESULT   CoCreateInstance(REFCLSID   rclsid,   LPUNKNOWN   pUnkOuter   =   NULL,   DWORD   dwClsContext   =   CLSCTX_ALL)   throw(),   其中的

pUnkOuter决定所创造的组件是独立的还是聚合的。

CoCreateInstance
              ¦
              ¦ 
       pUnkOuter   ==   NULL     -----yes----->   "new "   CComObject <CClass> 
                                          ¦ 
                                         no
                                          ¦
                      "new "   CComAggObject <CClass>

这里的 "new ",其实就是CComCreator.CreateInstance(pv,   riid,   ppv);
其中的pv   =   pUnkOuter   ;

template    < class    T1 >  
class    CComCreator 

public
    
static    HRESULT   WINAPI   CreateInstance( void *    pv,   REFIID   riid,   LPVOID *    ppv) 
    { 
        ATLASSERT(ppv   
!=    NULL); 
        
if    (ppv    ==    NULL) 
            
return    E_POINTER; 
        
* ppv    =    NULL; 

        HRESULT   hRes   
=    E_OUTOFMEMORY; 
        T1
*    p    =    NULL; 
        ATLTRY(p   
=     new    T1(pv)) 
        
if    (p    !=    NULL) 
        { 
            p
->  SetVoid(pv); 
            p
->  InternalFinalConstructAddRef(); 
            hRes   
=    p ->  FinalConstruct(); 
            
if    (SUCCEEDED(hRes)) 
            hRes   
=    p ->  _AtlFinalConstruct(); 
            p
->  InternalFinalConstructRelease(); 
            
if    (hRes    ==    S_OK) 
                hRes   
=    p ->  QueryInterface(riid,   ppv); 
            
if (hRes    !=    S_OK) 
                delete   p; 
        } 
        
return    hRes; 
    } 
}; 


这个过程对于独立或聚合来说,没有什么大的区别。

关于组件聚合,需要分两方面讨论:
1。 聚合别的组件(外部)

class    ATL_NO_VTABLE   CComplexMath   :   
public    CComObjectRootEx  < CComSingleThreadModel >  , 
public    CComCoClass  < CComplexMath,    & CLSID_ComplexMath >  , 
public    IDispatchImpl  < IComplexMath,    & IID_IComplexMath,    & LIBID_COMPLEXCALCULATORLib >  

public
CComplexMath() 



DECLARE_REGISTRY_RESOURCEID(IDR_COMPLEXMATH) 

DECLARE_PROTECT_FINAL_CONSTRUCT() 

BEGIN_COM_MAP(CComplexMath) 
COM_INTERFACE_ENTRY(IComplexMath) 
COM_INTERFACE_ENTRY_AGGREGATE   (IID_ISimpleMath,   ptrUnk)   
<===    增加要暴露的内部组件接口,到内部组件IUnknown接口的映射 
COM_INTERFACE_ENTRY(IDispatch) 
END_COM_MAP() 

//    IComplexMath 
public
    STDMETHOD(Divide)(
/* [in] */     int    x,    /* [in] */     int    y,    /* [out,retval] */     int *    z   ); 

    
// Aggregation:   Add   the   controlling   macro,   finalconstruct   and   final   release 
    DECLARE_GET_CONTROLLING_UNKNOWN()  <===    获取外部IUnknown接口指针 
    IUnknown
*    ptrUnk;  <===    内部组件的IUnknown接口指针 

    HRESULT   FinalConstruct() 
    { 
          
return   CoCreateInstance(CLSID_SimpleMath,   GetControllingUnknown(),CLSCTX_ALL,   IID_IUnknown,   ( void ** ) & ptrUnk); 

    
<===    创建内部组件(引入pUnkOuter),并获得内部组件的IUnknown接口指针ptrUnk 
    } 

    
void    FinalRelease() 
    { 
      ptrUnk
->  Release();  <===    释放内部组件的IUnknown接口指针 
    } 
    
// End 

}; 

聚合接口映射宏:
COM_INTERFACE_ENTRY_AGGREGATE   (IID_ISimpleMath,   ptrUnk)

展开为:
#define   COM_INTERFACE_ENTRY_AGGREGATE(iid,   punk)/
{&iid,/
(DWORD_PTR)offsetof(_ComMapClass,   punk),/ //   dw中存储的是内部对象接口指针在外部对象中的偏移量
_Delegate},

ATL使用_Delegate来支持聚合。
static    HRESULT   WINAPI   _Delegate( void *    pv,   REFIID   iid,    void **    ppvObject,   DWORD_PTR   dw) 

    HRESULT   hRes   
=    E_NOINTERFACE; 
    IUnknown
*    p    =     * (IUnknown ** )((DWORD_PTR)pv    +    dw);        //    通过偏移量得到内部接口指针 
     if    (p    !=    NULL) 
    hRes   
=    p ->  QueryInterface(iid,   ppvObject);      //    查询得到所要求的内部接口指针 
     return    hRes; 


ATLINLINE   ATLAPI   AtlInternalQueryInterface(
void *    pThis, 
const    _ATL_INTMAP_ENTRY *    pEntries,   REFIID   iid,    void **    ppvObject) 

    ATLASSERT(pThis   
!=    NULL); 
    
//    First   entry   in   the   com   map   should   be   a   simple   map   entry 
    ATLASSERT(pEntries ->  pFunc    ==    _ATL_SIMPLEMAPENTRY); 
    
if    (ppvObject    ==    NULL) 
        
return    E_POINTER; 
    
* ppvObject    =    NULL; 
    
if    (InlineIsEqualUnknown(iid))    //    use   first   interface 
    { 
        IUnknown
*    pUnk    =    (IUnknown * )((INT_PTR)pThis + pEntries ->  dw); 
        pUnk
->  AddRef(); 
        
* ppvObject    =    pUnk; 
        
return    S_OK; 
    } 
    
while    (pEntries ->  pFunc    !=    NULL) 
    { 
        BOOL   bBlind   
=    (pEntries ->  piid    ==    NULL); 
        
if    (bBlind   ¦ ¦   InlineIsEqualGUID( * (pEntries ->  piid),   iid)) 
        { 
            
if    (pEntries ->  pFunc    ==    _ATL_SIMPLEMAPENTRY)    // offset 
            { 
                ATLASSERT(
! bBlind); 
                IUnknown
*    pUnk    =    (IUnknown * )((INT_PTR)pThis + pEntries ->  dw); 
                pUnk
->  AddRef(); 
                
* ppvObject    =    pUnk; 
                
return    S_OK; 
            } 
            
else     // actual   function   call 
            { 
                HRESULT   hRes   
=    pEntries ->  pFunc(pThis,          <==    使用_Delegate来支持聚合。   
                iid,   ppvObject,   pEntries
->  dw); 
                
if    (hRes    ==    S_OK   ¦ ¦   ( ! bBlind    &&    FAILED(hRes))) 
                
return    hRes; 
            } 
        } 
        pEntries
++
    } 
    
return    E_NOINTERFACE; 

由此可见,接口映射表就像一个“路由器”---将不同的接口请求转发到外部或内部组件。

BEGIN_COM_MAP(CComplexMath)
COM_INTERFACE_ENTRY(IComplexMath)
COM_INTERFACE_ENTRY_AGGREGATE   (IID_ISimpleMath,   ptrUnk)   <===   增加要暴露的内部组件接口,到内部组件IUnknown接口的映射
COM_INTERFACE_ENTRY(IDispatch)
END_COM_MAP()

2。被聚合的组件(内部)
一个组件以被聚合形式存在时,最关键在于---pUnkOuter   的引入(p   =   new   T1(pv))。

被聚合的组件实现了两套:AddRef,   Release   和   QueryInterface。

一套用于内部控制;
一套用于外部控制--   通过pUnkOuter;
template    < class    contained >  
class    CComAggObject   : 
public    IUnknown, 
public    CComObjectRootEx  <    contained::_ThreadModel::ThreadModelNoCS    >  

public
    .............. 

    STDMETHOD_(ULONG,   AddRef)()   {
return    InternalAddRef();}  //    内部 
    STDMETHOD_(ULONG,   Release)()  //    内部 
    { 
        ULONG   l   
=    InternalRelease(); 
        
if    (l    ==     0
        delete   
this
        
return    l; 
    } 
    STDMETHOD(QueryInterface)(REFIID   iid,   
void     **    ppvObject)    //    内部 
    { 
        ATLASSERT(ppvObject   
!=    NULL); 
        
if    (ppvObject    ==    NULL) 
            
return    E_POINTER; 
        
* ppvObject    =    NULL; 

        HRESULT   hRes   
=    S_OK; 
        
if    (InlineIsEqualUnknown(iid)) 
        { 
            
* ppvObject    =    ( void * )(IUnknown * ) this
            AddRef(); 

            ......... 

        } 
        
else  
            hRes   
=    m_contained._InternalQueryInterface(iid,   ppvObject);  //    
         return    hRes; 
    } 

    ... 

    CComContainedObject 
< contained >    m_contained; 
}; 

template   
< class    Base >     // Base   must   be   derived   from   CComObjectRoot 
class    CComContainedObject   :    public    Base 

public
    typedef   Base   _BaseClass; 
    CComContainedObject(
void *    pv)   {m_pOuterUnknown    =    (IUnknown * )pv;} 
    #ifdef   _ATL_DEBUG_INTERFACES 
    
~ CComContainedObject() 
    { 
        _AtlDebugInterfacesModule.DeleteNonAddRefThunk(_GetRawUnknown()); 
        _AtlDebugInterfacesModule.DeleteNonAddRefThunk(m_pOuterUnknown); 
    } 
    
#endif  

    STDMETHOD_(ULONG,   AddRef)()   {
return    OuterAddRef();}  //    外部 
    STDMETHOD_(ULONG,   Release)()   { return    OuterRelease();}  //    外部 
    STDMETHOD(QueryInterface)(REFIID   iid,    void     **    ppvObject)  //    外部 
    { 
       
return    OuterQueryInterface(iid,   ppvObject); 
    } 
    template   
< class    Q >  
    HRESULT   STDMETHODCALLTYPE   QueryInterface(Q
**    pp) 
    { 
        
return    QueryInterface(__uuidof(Q),   ( void ** )pp); 
    } 
    
// GetControllingUnknown   may   be   virtual   if   the   Base   class   has   declared 
    
// DECLARE_GET_CONTROLLING_UNKNOWN() 
    IUnknown *    GetControllingUnknown() 
    { 
        #ifdef   _ATL_DEBUG_INTERFACES 
        IUnknown
*    p; 
        _AtlDebugInterfacesModule.AddNonAddRefThunk(m_pOuterUnknown,   _T( 
" CComContainedObject  " ),    & p); 
        
return    p; 
        
#else  
        
return    m_pOuterUnknown; 
        
#endif  
    } 
}; 

BEGIN_COM_MAP(CAdvance)
COM_INTERFACE_ENTRY(IAdvance)
COM_INTERFACE_ENTRY_AGGREGATE(IID_IMath1,   m_pSimpleUnknown)----------
COM_INTERFACE_ENTRY_AGGREGATE(IID_IMath2,   m_pSimpleUnknown)-------   路由
END_COM_MAP()           ¦
          ¦
          ¦
(内部被聚合类)
BEGIN_COM_MAP(CSimple)
COM_INTERFACE_ENTRY(IID_IMath1)
COM_INTERFACE_ENTRY(IID_IMath2)
END_COM_MAP()

 

你可能感兴趣的:(null,delete,存储,Class,interface,路由器)