《深入解析ATL》5.6.1小节“接口映射表链”中说到,派生类的接口映射表通过 COM_INTERFACE_ENTRY_CHAIN 来使用基类的接口映射表。同时强调,接口映射表的第一个项必须是一个简单项,所以在派生类的接口映射表中至少一个派生类的接口放在第一项,即说明 COM_INTERFACE_ENTRY_CHAIN 不能放在第一项。最后还说到,如果派生类没有其他接口,那么可把 IUnknown 放在第一项。例如:class CBetterBeachBall: public CBeachBall
{
public:
  BEGIN_COM_MAP(CBetterBeachBall)
    COM__INTERFACE_ENTRY(IUnknown)
    COM__INTERFACE_ENTRY_CHAIN(CBeachBall)
  END_COM_MAP()
} 问题是:如果 CBeachBall 实现了两个以上的接口,那么 COM__INTERFACE_ENTRY(IUnknown)会不会产生二义性?

解决方案 »

  1.   

    不会产生二义性,IUnknown接口是每个接口虚表中都存在的,但三个方法只实现了一次,也就是说无论这个IUnknown属于哪个接口,它们的实现都是相同的。其次,在接口映射表中加不加IUnknown的入口都可以,即使不加,这个映射表中也有隐含的映射条目,加多次也没关系,无非是多了几个完全相同的if判断而已,但加上可以解决某些编译问题。
      

  2.   


    你意思是说书上例子写错了,应该是下面这样?!class CBetterBeachBall: 
      public CBeachBall,
      public IUnknown{
    public:
      BEGIN_COM_MAP(CBetterBeachBall)
      COM__INTERFACE_ENTRY(IUnknown)  
       COM__INTERFACE_ENTRY_CHAIN(CBeachBall)
      END_COM_MAP()
    }  
      

  3.   

    no, every interface should inherit IUnknow
      

  4.   

    ATL_NO_VTABLE 宏可以改变 虚表指针在内存的分布。如果是多重继承的话,那么中间的类是不生成虚表的。
      

  5.   

    Table-Driven QueryInterface一节中对IUnknow有特别处理
    <cpp>
    ATLINLINE ATLAPI AtlInternalQueryInterface(                       
        void* pThis,                                                  
        const _ATL_INTMAP_ENTRY* pEntries,                            
        REFIID iid,                                                   
        void** ppvObject)                                             
    {
    ...
    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) {
    ...//对于不是IUnknown 的iid进行查表
        }                                                             
        return E_NOINTERFACE;                                         
    }
    </cpp>
    对于IUnknown,ATL只检查map的第一项,并且做类似static_cast找到vtbl定位,所以查找IUnknown不会出现branch
    对于非IUnknown才会一个一个检索.
      

  6.   

    没有错哈 你可以先看com技术内幕,看完你就明白了!你讲的那个问题那个书上也有讲啊!