2015-09-24 77 views
0

鑑於打印功能:C++指針函數和非指針功能

void print(int i) 
{ 
    cout << i << endl; 
} 

爲什麼我們允許這樣做的主要功能

void (*bar)(int); 
bar = &print; 

但不是這樣的:

void fizz(int); 
fizz = print; 

但是,當涉及到函數參數時,我們可以將指針傳遞給函數n或該功能的副本:

void foo(void (*f)(int)) 
{ 
    (*f)(1); 
} 

void test(void f(int)) 
{ 
    f(1); 
} 

有人知道這些差異的原因嗎?

+0

bar的定義是函數指針的正確語法,而fizz只是定義函數簽名的語法。我不熟悉你的函數測試的語法,所以我希望別人可以清除它。 – Parappa

+0

請參閱http://stackoverflow.com/questions/26559758/function-to-function-pointer-decay – sfjac

+0

就像使用數組類型作爲函數參數一樣,它將轉換爲指向第一個元素的指針。顯然這隻能在函數聲明中使用。不尋常的,但不是沒有使用。 – Macmade

回答

0

函數指針可以指向任何具有相同參數和返回類型的函數。在上面的代碼中,「bar」是指針,而bar=&print表示讓bar指向print。但是,一個函數不能有=的功能。
函數指針的好處在於,只要函數具有相同的參數和返回類型,它就可以指向ANY函數。當函數指針作爲另一個函數的參數時,這非常有用。
將函數用作參數時,傳遞的實際內容是函數的地址。函數不能被解引用(即不能作爲函數傳遞)。我不太清楚,但看起來您的footest的實現是相同的。

+0

啊,我想沒有星號,我通過了一個函數的副本。所以即使使用函數作爲參數,函數仍然是一個地址。那麼這意味着沒有真正的理由在foo(void f(int))上使用void foo(void(* f)(int))? – Dobob

+0

相反,總是使用函數指針作爲參數。它顯示了事情應該是什麼。 –

0

我會建議性病閱讀起來::從函數C++ 11: http://en.cppreference.com/w/cpp/utility/functional/function

這將允許你做的越多,你打算什麼,在哪裏無效(INT)是指返回類型和列表您的功能參數:

void fizz(std::function<void(int)> f) 
{ 
    f(1); 
} 

功能現在是一流的數據類型。你甚至可以在沒有任何痛苦的語法的情況下爲類方法使用函數。您還可以在許多情況下使用自動進行惰性/動態替換。您也可以使用相同的設置來執行有趣的事情,例如異步啓動功能。

auto used_to_call_fizz = fizz; 
used_to_call_fizz(f); 
std::async(used_to_call_fizz, f); 
+1

'auto'不是動態的。它基於分配靜態地確定變量的類型,並且在標準沒有明確定義表達的類型的地方是必需的,例如在'std :: bind'或lambda函數的情況下。 – CoffeeandCode

+0

auto是動態的,如果你改變了嘶嘶聲的類型(比如說改變返回類型),你不需要重寫該行,但是是的,你是正確的,它是在編譯時確定的,因此類型安全。 – Ryan

+1

它在任何意義上都不是動態的。它是靜態的。這就像調用「decltype」動態因爲它可以確定多種不同類型':^) – CoffeeandCode

0

每個函數都有自己的地址,你可以看到它是一個array。功能void fizz(int)void print(int i)有不同的內存地址,所以fizz = print;會出錯。但是您使用void (*bar)(int);,它顯示了用於指向函數的函數指針。當您使用bar=&print時,它將初始化bar指針,然後得到正確的答案。順便說一下,您可以使用bar=print,因爲它們具有與array相同的內存地址。我希望這可以幫助你。