对《深入解析ATL》5.6.1小节中一个说法的疑惑!
《深入解析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)会不会产生二义性?
[解决办法]
刚看到第二章、只能帮顶了。
我理解书上的意思应该是指从CBetterBeachBall的直接多重继承,而不是间接多重继承。
[解决办法]
不会产生二义性,IUnknown接口是每个接口虚表中都存在的,但三个方法只实现了一次,也就是说无论这个IUnknown属于哪个接口,它们的实现都是相同的。其次,在接口映射表中加不加IUnknown的入口都可以,即使不加,这个映射表中也有隐含的映射条目,加多次也没关系,无非是多了几个完全相同的if判断而已,但加上可以解决某些编译问题。
[解决办法]
no, every interface should inherit IUnknow
[解决办法]
ATL_NO_VTABLE 宏可以改变 虚表指针在内存的分布。如果是多重继承的话,那么中间的类是不生成虚表的。
[解决办法]
今天刚借的这本书,打算好好学习
[解决办法]
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才会一个一个检索.
[解决办法]
没有错哈 你可以先看com技术内幕,看完你就明白了!你讲的那个问题那个书上也有讲啊!