一個類中的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
進級,或Ib在0x0000000b
獲得一個指向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中的同一個成員開始,然後在最後加上額外的成員。
有一篇關於VC++實現的舊文章[這裏](http://www.openrce.org/articles/files/jangrayhood.pdf),我假設基本原理沒有改變(當然,其他的實現將會不同)。 – 2012-03-22 21:04:20
它爲什麼重要? vtables是實現細節。 C++標準沒有vtable的概念。 – fredoverflow 2012-03-22 21:31:23
@FredOverflow不幸的是,COM對象接口映射到他們的vtable實現。這可能只是一個COM問題。 – 2012-03-22 21:53:33