如何在C++中实现多个COM接口?

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函数),我能为每个接口实现不同的方法吗?

2个回答

7
是的,每个继承接口都有一个v-table。使用static_cast<>返回它。编译器确保在继承接口中共享通用方法,它填充每个v-table插槽与指向相同函数的指针。所以你只需要一个AddRef、Release和QueryInterface的实现,正是你想要的。这一切都不是偶然发生的。
只有当coclass实现多个接口具有相同的方法,而你不希望给出相同的实现时,这才会成为问题。IConnectionPoint::Advise()方法是一个臭名昭著的例子。或者是DAdvise()?不幸的是,我不记得它与什么冲突以及如何解决,它被ATL Internals覆盖了。非常好的书。

1
谢谢!我自己做了一些阅读,发现它不仅创建了不同的VTable,还创建了“thunk”函数来修复指针,然后重定向回公共函数。 - Martin

3

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

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

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接