如果类实现多于1个接口,那么VTable的方法指针顺序是什么?

时间:2012-03-22 20:42:41

标签: c++ com vtable

我知道如果A类实现了例如IUnknown和IComSomething1,那么VTable的方法顺序将首先是IUnknown而不是IComSomething1。据我所知,这总是顺序,因为IComSomething1继承了IUnknown。

但是如果A类实现了IUnknown和IComSomething1以及IComSomething2,那么顺序是什么? IComSomething1和IComSomething2之间的VTable方法指针的顺序是什么?

(这个问题不仅适用于COM,但它来自COM问题,它通过vtable偏移调用函数)。

我试图在那里找到一些答案,但我找不到任何直接,明确的答案。

谢谢! : - )

1 个答案:

答案 0 :(得分:4)

类中vtable成员的顺序没有明确定义。实际上,您可以(并且将会!)在vtable指针之间找到数据成员。如果您正在编写COM,那么在将其写入您将结果输入的指针之前,应该转换为要在QueryInterface中返回的任何接口。这就是:

HRESULT QueryInterface(REFIID riid, LPVOID *ppvObject) {
  if (*riid == IID_MY_INTERFACE) {
    *ppvObject = static_cast<IMyInterface *>(this);
    return S_OK;
  } else if (*riid == IID_SOMETHING_ELSE) {
    *ppvObject = static_cast<ISomethingElse *>(this);
    return S_OK;
  } else /* ... */
}

编译器将负责为您找到适合该接口的偏移量。

至于它实际上是如何工作的,想想这意味着什么 - 每个接口必须作为对象存在于对象内部偏移的某个子范围内。假设你有一个类似于此的类层次结构:

class IA { virtual void foo() = 0; int x;};
class IB { virtual void bar() = 0; int y; };
class C : public IA, public IB { int bar; };

您的内存中布局可能如下所示:

00000000 vtable ptr for C
00000004 vtable ptr for Ia
00000008 int x
0000000b vtable ptr for Ib
00000010 int y
00000014 int bar

在这里,您可以通过在班级中获取偏移0x00000004或在0x0000000b获取Ib来获取指向Ia的指针。

在某些情况下,可能会进一步优化这一点:

00000000 vtable ptr for C and Ia
00000004 int x
00000008 vtable ptr for Ib
0000000b int y
00000010 int bar

我不确定win32 C ++ ABI是否真的这样做了。如果你这样做,那么C vtable以与Ia vtable相同的成员开始,然后在最后添加额外的成员。