2012-01-03 218 views
-1

我有一個代碼。這段代碼爲什麼要編譯?

class A 
{ 
public: 
    int foo(int i) 
    { 
     return i; 
    } 
}; 

int foo(int i) 
{ 
    return i; 
} 

int (A::*ptrFoo)(int) = NULL; 
int (*_foo)(int) = NULL; 

int main() 
{ 
    ptrFoo = &A::foo; 
    _foo = foo; 

    (*_foo)++++++++++++++(10); //This dont compile... 

    A a; 
    (a.*ptrFoo)+++++++++++++++++(10); //This compiles ???? 

} 

請告訴我它是什麼?一個未定義的行爲或什麼?我編譯它在VS2008.Strangely最後一行代碼編譯成功。

+2

'++++++++++++++'是七個半後增量運算符。據推測,編譯器已經陷入了一半。 – 2012-01-03 05:47:14

+0

您是否將它編譯爲C和C++?或者你爲什麼包含這兩個標籤? – 2012-01-03 05:53:21

+0

我編譯它在c + +(VS2008).i將刪除「C」標記 – YAHOOOOO 2012-01-03 06:01:09

回答

2

這兩個表達式都不應該編譯:在C++中,不能對指向函數或成員函數的指針或函數類型或成員函數執行算術運算。程序中的兩個表達式分別嘗試對函數和成員函數執行算術運算。

如果您的編譯器接受第二個表達式,這是由於編譯器中的錯誤。

1

首先請注意,指向函數的指針與指向成員函數的指針不同。

你的第一個例子是一個指向普通函數的指針。它包含該函數的實際內存地址。當你取消引用((*_foo))時,你會得到這個函數本身,算術運算包括++在函數上(函數指針)是毫無意義的。

第二個是另一個故事,指向類成員函數的指針不會在內存中攜帶該函數的地址。實際上編譯器如何管理成員函數是特定於實現的。指向成員函數的指針可能包含一些地址或者某些編譯器特定的信息。這種類型的算術也沒有意義。

因此,我們不知道(a.*ptrFoo)的價值是什麼,但在您的情況下MSVC2008設法編譯它,無論是因爲錯誤還是設計。

順便說一下,GCC不會編譯這兩個語句中的任何一個,並在兩者上拋出錯誤。

無論你是偶數還是奇數,無論如何,我們正在做算術。 (如果有奇數+那麼就沒有函數調用,就像在第二個例子中一樣,你將函數遞增8次,然後最後一個剩餘的+增加10個結果。正試圖改變一個函數/成員函數指針。)

+0

「編譯器如何管理成員函數是特定於實現的」非成員函數的實現也是一個實現細節。 – 2012-01-03 06:26:47

+0

@JamesMcNellis:你說的對,但是每一個普通的函數在內存中都有一個明確的地址,不是嗎?但是,成員函數的「地址」並不是我們所知道的;每個編譯器都有自己的實現類的範例。 – Hossein 2012-01-03 06:30:54