2014-03-05 161 views
6

common.h向前聲明的類的成員函數指針Test和功能接收一個成員函數指針:向前聲明的類

class Test; 

void func(const Test &t, int (Test::*f)() const, int x, int y); 

在源文件target.cpp,我定義函數,使得

#include "common.h" 

void func(const Test &t, int (Test::*f)() const, int x, int y) { 
    std::cout << "f: " << (t.*f)() << ", x: " << x << ", y: " << y << std::endl; 
} 

在我的主文件中,我定義了類Test並使用函數func

class Test { 
public: 
    int example() const { return 1; } 
}; 

#include "common.h" 

int main() { 
    Test t; 
    func(t, &Test::example, 0xaaaaaaaa, 0xbbbbbbbb); 
    return 0; 
} 

顯然這有點臭,因爲指向成員函數的指針有時不僅僅是一個簡單的指針。但由此產生的行爲有點壓倒性:給定的參數0xaaaaaaaa0xbbbbbbbb將不會正確傳遞給函數。或者更確切地說,功能func解釋給定的堆棧不同於調用者將數據壓入堆棧。 f的大小取決於該類是隻是前向聲明還是實際定義的。與Visual Studio 2013編譯的輸出是:

f: 1, x: 0, y: 2130567168 

我想,如果一個向前聲明就足夠了,它真的不要緊是否有給予與否的定義。

+0

「0xaaaaaaaa」和「0xbbbbbbbb」不能表示爲「int」(在windows調用約定下,請參見[MSDN](http://msdn.microsoft.com/zh-cn/library/296az74e.aspx))。縮小轉換調用未定義的行爲。您是否嘗試過使用較小的數字? – Mankarse

+0

我選擇這些值是爲了在我的堆棧中清楚地看到它們。當然,如果您選擇較小的值,它也不起作用。我認爲,縮小是在編譯期間完成的,因爲這些值是文字並且綁定到整數值。 – phlipsy

+0

恕我直言,它是不正確的,因爲這個函數可能是虛擬或不虛擬 – borisbn

回答

4

默認情況下,MSVC有利於指向成員的速度超過正確性。您可以通過傳遞編譯器標誌/vmg來強制它按照標準工作。

+0

哦,那太棒了!我在這個問題上失去了一整天。 – phlipsy

+0

@phlipsy同樣的事情發生在我身上(即我也很難學會這個標誌)。 – Angew

+0

你有這方面的一些額外的信息,鏈接等? – phlipsy