我知道如果A类实现了例如IUnknown和IComSomething1,那么VTable的方法顺序将首先是IUnknown而不是IComSomething1。据我所知,这总是顺序,因为IComSomething1继承了IUnknown。
但是如果A类实现了IUnknown和IComSomething1以及IComSomething2,那么顺序是什么? IComSomething1和IComSomething2之间的VTable方法指针的顺序是什么?
(这个问题不仅适用于COM,但它来自COM问题,它通过vtable偏移调用函数)。
我试图在那里找到一些答案,但我找不到任何直接,明确的答案。
谢谢! : - )
答案 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相同的成员开始,然后在最后添加额外的成员。