接口着色

接口着色--就是对于两个布局相同的接口的调用是兼容的。

如下:ISphere和IRedSphere布局相同,vptr   table相同。

struct   ISphere   :   IUnknown   {
    STDMETHOD(Rotate)(long   nDegrees,   long*   pnOrientation)   =0;
    STDMETHOD(Twirl)(long   nVelocity)   =0;
};

struct   IRedSphere   {
    //   Colored   IUnknown   methods
    STDMETHOD(RedQueryInterface)(   REFIID   riid,   void**   ppv)   =0;
    STDMETHOD_(ULONG,   RedAddRef)()   =0;
    STDMETHOD_(ULONG,   RedRelease)()   =0;

    //   Uncolored   ISphere   methods
    STDMETHOD(Rotate)(long   nDegrees,   long*   pnOrientation)   =0;
    STDMETHOD(Twirl)(long   nVelocity)   =0;
};

实现组件时使用了IRedSphere接口进行实现。
class   CDesktopGlobe   :
    public   CComObjectRootEx <CComSingleThreadModel> ,
    public   IRedSphere,
    public   IGlobe,
    public   IPlanet   {
public:
    ...
BEGIN_COM_MAP(CDesktopGlobe)
    //   Expose   IRedShere   when   ISphere   is   requested
    COM_INTERFACE_ENTRY_IID(IID_ISphere,   IRedSphere)     <===   当查询ISphere接口时,返回IRedSphere接口。
    COM_INTERFACE_ENTRY(IGlobe)
    COM_INTERFACE_ENTRY(IPlanet)
END_COM_MAP()
    ...
    //   Colored   method   implementations
    STDMETHODIMP   RedQueryInterface(REFIID   riid,   void**   ppv)
    {   return   GetUnknown()-> QueryInterface(riid,   ppv);   }
    STDMETHODIMP_(ULONG)   RedAddRef()   {
        _ThreadModel::Increment(&m_cRefSphere);
        return   GetUnknown()-> AddRef();
    }
    STDMETHODIMP_(ULONG)   RedRelease()   {
        _ThreadModel::Decrement(&m_cRefSphere);
        return   GetUnknown()-> Release();
}

private:
    long   m_cRefSphere;
};


这样,客户端对于查询ISphere接口时返回IRedSphere接口毫不知晓,一样使用。
只是这时实际调用的是IRedSphere实现。

void   TryRotate(IUnknown*   punk)   {
    ISphere*   ps   =   0;

    //   Implicit   AddRef   really   a   call   to   RedAddRef
    if(SUCCEEDED(punk-> QueryInterface(IID_ISphere,   (void**)&ps)))   {             <===   实际返回的是IRedSphere接口
        //   ps   actually   points   to   an   IRedSphere*

        ps-> Rotate();   <===   IRedSphere实现
        ps-> Release();   //   Really   a   call   to   RedRelease
    }

比较COM_INTERFACE_ENTRY_IID(IID_ISphere,   IRedSphere)和
COM_INTERFACE_ENTRY_IID(IDispatch,   IUse2)  
两者有异曲同工之妙!都是呼叫一个接口,返回另外一个接口.
只不过IUse2和IDispatch具有继承关系,而ISphere和IRedSphere接口布局一致.

总之,能这么作的根本是接口兼容,或可以互相转化. 
 

你可能感兴趣的:(struct,table,Class,interface,methods)