【问题标题】:How does implementing multiple COM interfaces work in C++?如何在 C++ 中实现多个 COM 接口?
【发布时间】:2011-03-03 08:01:01
【问题描述】:

我正在尝试了解 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 的角度来看,接口指针只是指向 VTable 的指针。所以我认为这意味着 C++ 能够使用 static_cast 返回任何已实现接口的 VTable。

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

【问题讨论】:

    标签: c++ com static-cast multiple-interface-implem


    【解决方案1】:

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

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

    【讨论】:

    • 谢谢!我自己做了一些阅读,我发现它不仅创建了不同的 VTable,而且还创建了“thunk”函数来修复指针,然后再重定向回通用函数。
    【解决方案2】:

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

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

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

    【讨论】:

      猜你喜欢
      • 2022-01-16
      • 1970-01-01
      • 2011-02-26
      • 1970-01-01
      • 2011-09-29
      • 2021-02-03
      • 1970-01-01
      • 1970-01-01
      • 2014-06-16
      相关资源
      最近更新 更多