2012-03-22 66 views
1

我知道,如果A類例如IUnknown和IComSomething1實現,不是虛函數表的方法,以便將第一IUnknown和比IComSomething1。據我所知,這總是順序,因爲IComSomething1繼承了IUnknown。如果類實現多個接口,那麼VTable的方法指針順序是什麼?

但是,如果A類實現IUnknown和IComSomething1和IComSomething2,那麼順序是什麼? IComSomething1和IComSomething2之間的VTable方法指針的順序是什麼?

(這個問題不僅適用於COM,而且它出自一個COM問題,它通過一個vtable偏移量調用函數)。

我試圖找到一些答案「在那裏」,但我找不到任何直接,清晰的答案。

謝謝! :-)

+3

有一篇關於VC++實現的舊文章[這裏](http://www.openrce.org/articles/files/jangrayhood.pdf),我假設基本原理沒有改變(當然,其他的實現將會不同)。 – 2012-03-22 21:04:20

+1

它爲什麼重要? vtables是實現細節。 C++標準沒有vtable的概念。 – fredoverflow 2012-03-22 21:31:23

+1

@FredOverflow不幸的是,COM對象接口映射到他們的vtable實現。這可能只是一個COM問題。 – 2012-03-22 21:53:33

回答

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進級,或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中的同一個成員開始,然後在最後加上額外的成員。

+1

還有一箇中間的優化,其中'C'虛函數表與'Ia'虛函數表共享的,但有兩個指向它。這可以獨立於ABI來完成,並且仍然爲您提供更好的參考位置。 – MSalters 2012-03-23 08:38:31

+0

@ MSalters的確,你也許可以用這種方式合併'B' vtable。 – bdonlan 2012-03-24 02:23:39

相關問題