2011-09-18 59 views
4

我很困惑函數指針參數的形式。以下兩種:函數指針作爲C++中的參數?

int fun(int (*g)()) 
{ 
    cout << g() << endl; 
} 

int fun(int g()) 
{ 
    cout << g() << endl; 
} 

這兩個定義都很好。但是,正如你已經注意到了,也有在這兩個函數原型一些差異:

  • 第一個採用參數int (*g)()
  • 而第二個需要參數int g()

我的問題是他們之間有什麼區別?

回答

4

在第二種情況下,功能類型調整成爲指針到功能型,這使得這兩個功能是相同的。

int fun(int (*g)()); 
int fun(int g()); //same as above, after type adjustment 

的C++ 03標準說,在§13.1/ 3,區別僅在於存在一個

參數的聲明是一個功能類型,另一種是一個指針,指向同一函數類型是等價物也就是說,函數類型被調整爲指向函數類型(8.3.5)的指針。

[Example: 
    void h(int()); 
    void h(int (*)()); // redeclaration of h(int()) 
    void h(int x()) { } // definition of h(int()) 
    void h(int (*x)()) { } // ill-formed: redefinition of h(int()) 
] 

這同樣與數組指針adjustement,與我們比較熟悉:

int fun(int *a); 
int fun(int a[]); //same as above, after type adjustment 
int fun(int a[10]); //same as above, after type adjustment 

全部都是一樣的!

您可以通過我一個詳細的答案在這裏:

+0

你能解釋一下爲什麼C++將int g()衰減爲pointer-to-function-type,第一個是指向函數類型的指針,但第二個與第一個不同,正如你看到的那樣,符號。對於數組示例,它很容易理解。 – cheng

+0

@Nawaz:這裏有兩個截然不同的規則。函數類型的表達式在大多數上下文中被隱式轉換爲函數指針(包括像'foo()')的普通函數調用;這種轉換通常被稱爲* decay *。聲明爲函數類型的參數被*調整成爲指針函數參數。這兩條規則是相關的,但原則上語言可以有一個規則,但不是另一個。同樣也適用於陣列到指針衰減和陣列到指針參數的調整。 –

+0

@cheng:對於數組,爲什麼容易理解?因爲你更頻繁地看到這一點?另外,在這種情況下,C++標準允許指向函數類型轉換的函數類型。這就是它衰落的原因。 – Nawaz

2

您實際上不能擁有函數類型的參數。函數參數聲明爲類型爲「返回T的函數」調整後的爲「指向函數返回T的指針」。因此,您的兩個定義實際上是相同的。(C具有相同的規則。)

類似的規則適用於陣列參數聲明例如此:

int main(int argc, char *argv[]); 

實際上意味着此:

int main(int argc, char **argv); 
+0

爲你提供我能理解,因爲 「字符* argv的[]」 和 「字符** argv的」 確實是的例子相同。但對於int(* g)()和int g(),它們怎麼可能是相同的。 – cheng

+0

此外,如果兩者相同,那麼以下定義也是相同的?typedef int(* funP)(void); typedef int funP2(void); – cheng

+0

@ user508305:它們是相同的,因爲函數參數聲明在編譯時被調整爲指向函數的聲明。它類似於使'char * argv []'和'char ** argv'等價(但僅*作爲參數聲明)的調整規則。 –

1

大多數編譯器(例如MSVC,克++)接受所述第二形式作爲用於第一的簡寫。 Technicall你說你應該總是使用第一種形式。

+0

他們接受它,因爲語言要求他們這樣做。請參見C++ 2003標準中的8.3.5p3([dcl.fct])。 –

+0

@Keith在C標準中是否有等價的註釋? –

+0

是,[C99](http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf)6.7.5.3p7和p8。 –