我正在尝试了解有关浏览器帮助程序对象的this example code。
在内部,作者实现了一个暴露多个接口的类(IObjectWithSite,IDispatch)。
他的QueryInterface函数执行以下操作:
if(riid == IID_IUnknown) *ppv = static_cast<BHO*>(this);
else if(riid == IID_IObjectWithSite) *ppv = static_cast<IObjectWithSite*>(this);
else if (riid == IID_IDispatch) *ppv = static_cast<IDispatch*>(this);
我从C角度了解到,接口指针只是VTables的指针。所以我认为C ++能够使用static_cast返回任何已实现接口的VTable。
这是否意味着以这种方式构造的类在内存中有一堆VTable(IObjectWithSite,IDispatch等)? C ++对不同接口上的名称冲突做了什么(它们各自都有QueryInterface,AddRef和Release函数),我可以为每个接口实现不同的方法吗?
答案 0 :(得分:7)
是的,有多个v表,每个继承的接口一个。 static_cast&lt;&gt;归还它。编译器确保共享继承接口中的公共方法,它使用指向同一函数的指针填充每个v表槽。所以你只需要一个AddRef,Release,QueryInterface的实现。正是你想要的。这些都不是意外。
当coclass使用与不想要提供相同实现的相同方法实现多个接口时,这只是一个问题。 IConnectionPoint :: Advise()方法是一个臭名昭着的例子。还是DAdvise()?不幸的是,我不记得它与它发生了什么冲突以及它是如何解决的,它被ATL Internals所覆盖。非常好的书btw。
答案 1 :(得分:3)
在多重继承中,如果给定this
指针(指向第一个字节,01),则多个VTable按顺序排列,如下所示
[01] [02] [03] [04] [05] [06] [07] [08] [09] [10] [11] [12]
[VTableA的Ptr] [VTableB的Ptr] [VTableC的Ptr]
在C ++中,在多接口场景中每个函数原型只会生成一个实现。 但是对于正常继承方案,超类可能具有预定义的实现,而覆盖该函数的子代将使其VTable指向与父代不同的内容。