2014-09-12 61 views
0

我只是迷惑不解以下幾點:C++:在Visual Studio奇怪的虛成員函數指針2013

struct InterfaceABC { 
    virtual int printPolymorphic(int a) { 
     return a; 
    } 
} 

struct WithInterfaces : public InterfaceABC { 
    virtual int printPolymorphic(int a) { return a; } 
}; 

當我現在做的事:

address = &WithInterfaces::printPolymorphic; 

我在調試器中得到這樣的:

0x012e52a9 {unittests.exe![thunk]:MockMe::WithInterfaces::`vcall'{4,{flat}}' }'} 

但是,以下invokation將不會落在那裏:

((InterfaceABC*) new WithInterfaces())->printPolymorphic(3); 

的努力了一天後,我發現瞭如何「可靠」(鬼才)獲得使用C++代碼的實際虛擬地址,這給了我:

0x012e6ece {unittests.exe!MockMe::WithInterfaces::printPolymorphic(int)} 

那麼我們有什麼在這裏?

WithInterfaces().printPolymorphic(3) 

將調用

0x012e6ece {unittests.exe!MockMe::WithInterfaces::printPolymorphic(int)} 

等都將

((InterfaceABC*)new WithInterfaces())->printPolymorphic(3); 

...

Visual Studio中實現存根功能justfor我:)吧?我感到受寵若驚......但

address = &WithInterfaces::printPolymorphic; 

這將不會給你的功能地址。它會給你一個從未被調用過的函數的地址,如果沒有hackery,永遠不會被調用。

任何人都有一些很好的想法,爲什麼這是?也許還有一些關於如何真正得到真正的地址的想法,而不寫100行可怕的C + +瘋狂,可能沒有人,但我明白從所有的人將審查代碼?也就是說,以符合標準的方式...

回答

2

WithInterfaces::printPolymorphic的地址給出了一個thunk,它在調用時根據對象的類型分派到正確的函數中進行調用。

如果您在對象上調用虛擬成員函數,編譯器會發出代碼來查找指向該對象的虛函數表(vtable)中正確實現的指針,然後調用該函數。

指向虛擬成員函數的指針封裝了此行爲,您通過查看生成的thunk將其明確化。

它會給你一個地址到這,不會被調用,而不兩輪牛車永遠不能被調用的函數。

但是,它的邏輯包含在對虛函數的每一次調用中。

+0

嗯啞我......對,如果你通過該地址的東西,它不知道它的虛擬功能。所以它只會傳遞對象指針,然後thunk會做虛擬的事情。似乎有點合乎邏輯。至少我一天的努力沒有浪費。感謝您的澄清! – thesaint 2014-09-12 19:52:04