ATL多继承情况下接口的取得

多继承情况下接口的取得。

1.   多Dispatch接口
class   ATL_NO_VTABLE   CUse   :  
public   CComObjectRootEx <CComSingleThreadModel> ,
public   CComCoClass <CUse,   &CLSID_Parser> ,
public   IDispatchImpl < IUse1,   &IID_IParser,   &LIBID_netfeesrvLib,   /*wMajor   =*/   1,   /*wMinor   =*/   0>
public   IDispatchImpl < IUse2,   &IID_IParser,   &LIBID_netfeesrvLib,   /*wMajor   =*/   1,   /*wMinor   =*/   0>
{
public:

....
}

2.   接口分布结构:
pI   ----->   vptr1   ------>   IUnkonwn
      ¦                                    IDispatch
      dw                                IUse1
      ¦
        ---->   vptr2   ------>   IUnkonwn
                                           IDispatch
                                           IUse2

3.   接口映射表
BEGIN_COM_MAP(CUse)
COM_INTERFACE_ENTRY(IUse1)
COM_INTERFACE_ENTRY(IUse2)
COM_INTERFACE_ENTRY_IID(IDispatch,   IUse2)
END_COM_MAP()

#define   COM_INTERFACE_ENTRY(x)/
{&_ATL_IIDOF(x),   /
offsetofclass(x,   _ComMapClass),   /
_ATL_SIMPLEMAPENTRY},

#define   COM_INTERFACE_ENTRY_IID(iid,   x)/
{&iid,/
offsetofclass(x,   _ComMapClass),/
_ATL_SIMPLEMAPENTRY},

IUse1   ----   offsetofclass(IUse1,   _ComMapClass)   ---_ATL_SIMPLEMAPENTRY
IUse2   ----   offsetofclass(IUse2,   _ComMapClass)   ---_ATL_SIMPLEMAPENTRY
IDispatch   --   offsetofclass(IUse2,   _ComMapClass)   ---_ATL_SIMPLEMAPENTRY   <=======   选择IUse2计算接口偏移

4。
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, 
                iid,   ppvObject,   pEntries
->  dw); 
                
if    (hRes    ==    S_OK   ¦ ¦   ( ! bBlind    &&    FAILED(hRes))) 
                
return    hRes; 
            } 
        } 
        pEntries
++
    } 
    
return    E_NOINTERFACE; 



通过
IUnknown*   pUnk   =   (IUnknown*)((INT_PTR)pThis+pEntries-> dw);
来通过偏移量获得接口指针   ---   *ppvObject   =   pUnk;
即:基类指针(pUnk)象子类指针(pIUser1,   pIUser2)逆转换。
pIUser1   =   pUnk;
pIUser2   =   pUnk;

当要取得IDispatch时,根据程序作出的选择  
IDispatch   --   offsetofclass(IUse2,   _ComMapClass)   ---_ATL_SIMPLEMAPENTRY   <=======   选择IUse2计算接口偏移
在这里就是计算出pIUse2的偏移量,取得接口指针   ---   *ppvObject   =   pUnk;
即:基类指针(pUnk)象子类指针(pIDispatch)逆转换。
pIDispatch   =   pUnk;

由此可以看出,当实现象IDispatch这样的多继承时,需要类设计者决定IDispatch的走向:
IDispatch   --   offsetofclass(IUse2,   _ComMapClass)   ---_ATL_SIMPLEMAPENTRY   <=======   选择IUse2计算接口偏移 

也就是说:
在COM_INTERFACE_ENTRY_IID(IDispatch,   IUse2)中:
而IUse2决定取得接口指针的偏移量
IDispatch决定最终获得接口的类型--由*ppvObject   =   pUnk作隐式转换;

你可能感兴趣的:(null,Class,interface)