隱藏的this指標
對于非靜態成員函式來說,它攜帶了一個隱藏的”this”指標,這導致它不能滿足Win32回呼函式簽名的要求,這樣的結果就是:一個非靜態成員函式,不能作為一個合法的Win32回呼函式,
幸運的是,幾乎所有的回呼函式都提供了一些方法來感知呼叫背景關系,你可以將這個”this”指標作為一個背景關系環境來重構代碼,下面是一個例子:

有一些回呼函式簽名將它的第一個引數作為指示背景關系的引數(也叫做”參考資料”),湊巧的是,這個隱藏的”this”指標也正好是第一個引數,回顧我們之前關于呼叫約定的文章,可以知道對于成員函式的__stdcall呼叫約定也剛好匹配我們預期的堆疊布局,下面我們看一個WAITFORTIMERCALLBACK的例子:

請注意:”thiscall”呼叫約定不能匹配上面的場景,但是兩個”__stdcall”卻可以,幸運的是,編譯器足夠聰明,它能識別這個this指標,并對上面的靜態成員函式s_ThreadProc進行優化,

如果你有機會觀察一下編譯器為s_ThreadProc生成的匯編代碼,則你會發現:函式的實作實際上就是一個跳轉指令,因為編譯器已經意識到了兩種不同的呼叫約定,所以這里不需要做任何的翻譯作業,只是跳轉即可,

有些人可能想著更進一步:直接對CreateThread的第二個引數強制轉換為LPTHREAD_START_ROUTINE,這樣就可以完全不需要定義s_ThreadProc這個函式了,我強烈建議不這么做:因為我看到很多人都曾在轉換函式指標這個上吃過虧(關于這個議題,我后面會專門講一講),
總結
在上面的代碼中,雖然我們考慮到了兩個__stdcall呼叫約定,但是我們并沒有依賴它們,如果呼叫約定的巧合不能像預期那樣的作業,則代碼依然會正常作業,這個對于將代碼移植到其他架構的時候很重要,特別是當這個架構沒有上面所述的呼叫約定的巧合的時候,
最后
Raymond Chen的《The Old New Thing》是我非常喜歡的博客之一,里面有很多關于Windows的小知識,對于廣大Windows平臺開發者來說,確實十分有幫助,
本文來自:《Why do member functions need to be “static” to be used as a callback?》

轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/153581.html
標籤:其他
下一篇:SpringMVC(一)
