5

我正在尝试了解有关浏览器帮助程序对象的示例代码。

在内部,作者实现了一个暴露多个接口(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 的角度来看,接口指针只是指向 VTable 的指针。所以我认为这意味着 C++ 能够使用 static_cast 返回任何已实现接口的 VTable。

这是否意味着以这种方式构造的类在内存中有一堆 VTable(IObjectWithSite、IDispatch 等)?C++ 对不同接口上的名称冲突做了什么(它们每个都有一个 QueryInterface、AddRef 和 Release 函数),我可以为每个接口实现不同的方法吗?

4

2 回答 2

7

是的,有多个 v-table,每个继承接口一个。static_cast<> 返回它。编译器确保继承接口中的公共方法是共享的,它用指向同一函数的指针填充每个 v-table 槽。所以你只需要AddRef、Release、QueryInterface的一种实现。正是你想要的。这一切都不是意外。

只有当一个 coclass 使用您不想提供相同实现的相同方法实现多个接口时,这才会成为问题。IConnectionPoint::Advise() 方法是一个臭名昭著的例子。还是 DAdvise()?不幸的是,我不记得它与什么发生冲突以及它是如何解决的,它被 ATL Internals 覆盖。非常好的书顺便说一句。

于 2010-06-14T00:32:53.613 回答
3

this在多重继承中,如果给定指针(指向第一个字节,01),则多个 VTable 按如下格式排列

[01][02][03][04] [05][06][07][08] [09][10][11][12]
[VTableA 的指针][VTableB 的指针][VTableC 的指针]

在 C++ 中,在多接口场景中,每个函数原型只会生成 1 个实现。然而,对于正常的继承场景,超类可能具有预定义的实现,并且覆盖该函数的子类将使其 VTables 指向与父类不同的内容。

于 2010-06-14T01:25:39.903 回答