2015-11-04 21 views
5

Wiem, kiedy używamy nazwy funkcji jako wartości, funkcja jest automatycznie konwertowana na wskaźnik. spojrzeć na poniższy kod:przypisanie funkcji i wywołanie funkcji w C++?

int print(int a) 
{ 
    return a; 
} 

int main() 
{ 
    int (*p)(int) = print; 
    int (*q)(int) = &print; 

    cout << p(8) << endl; 
    cout << (*p)(8) << endl; 
} 

dlaczego int (*p)(int) = print;, druku jest wskaźnikiem, a int (*p)(int) = &print;, & druku jest adres do wskaźnika, co odpowiada?

Z drugiej strony, gdy używamy wskaźnika do funkcji wywoływania funkcji, dlaczego są one równoważne z p(8) i (*p)(8)?

+0

Myślę, że to tylko dla wygody , że nie musisz wyraźnie wskazywać funkcji funkcji podczas ich wywoływania. Jeśli użyjesz 'typedefs', możesz pracować ze wskaźnikiem funkcji bez użycia' * ', który jest całkiem niezły – user463035818

+2

Możliwy duplikat [Jak działa dereferencja wskaźnika funkcji?] (Http://stackoverflow.com/questions/2795575/how-does-dereferencing-of-a-function-pointer-happen) –

+0

@SimonKraemer dziękuję. Ale link wyjaśnia tylko dereferencję, moje pytanie obejmuje także przypisanie wskaźnika funkcji. – sydridgm

Odpowiedz

2

print jest funkcją, ale jest niejawnie zamienny do rodzaju wskaźnik funkcji. Cytat z cppref:

Funkcja do wskaźnika
lwartością typu funkcja T mogą być niejawnie przerobiony na prvalue wskaźnik do tej funkcji. Nie dotyczy to niestatycznych funkcji składowych, ponieważ nie istnieją wartości bezwymiarowe odnoszące się do niestatycznych funkcji składowych funkcji .

Więc w twoim przypadku:

int (*p)(int) = print; // Conversion happens. 
int (*q)(int) = &print; // Conversion does not happen. 

kopnięć niejawna konwersja automatycznie, gdy jest potrzebne do kompilacji programu i nie jest stosowana inaczej.

Jeśli chodzi o wywoływanie funkcji, chodzi o wbudowany operator połączeń funkcyjnych (). Zgodnie z cppref, wbudowany operator wywołań funkcji jest odpowiedni zarówno dla wyrażenia l-wartości, które odnosi się do funkcji i wskaźnika do funkcji. W danym przypadku:

p(8); // The function call operator is applied to a pointer to function. 
(*p)(8); // The function call operator is applied to an lvalue reference to function. 

przypadku odniesienia (kopalni nacisk):

wbudowanej wywołania funkcji ekspresji operatora
wywołanie funkcji, takich jak E (A1, A2, A3) , składa się z wyrażenia , które nazywa funkcję E, a następnie ewentualnie pustą listę wyrażeń A1, A2, A3, ... w nawiasach.Wyrażenie że nazwy funkcja może być

a) lwartość wyrażenie, które odnosi się do funkcji
b) wskaźnik funkcjonować
...

3

print to nie wskaźnik. Jego typ to int(int), a nie int(*)(int). Rozróżnienie to jest szczególnie ważne w rodzaju odliczenia

auto& f = print; //type of f is int(&)(int), not int(*(&))(int) 
template<typename Func> 
foo(Func& f); 
foo(print); //Func is deduced to be int(int), not int(*)(int) 

analogiczną do tablic, nie można kopiować funkcję „wartością”, ale można przejść wokół jego adres. Na przykład,

int arr[4];  //the type of arr is int[4], not int* 
int *a = arr; //automatic array-to-pointer decay 
int (*a)[4] = &arr; //type match 
int (*p)(int) = print; //automatic function-to-pointer decay 
int (*p)(int) = &print; //type match 

Teraz kiedy zadzwonić print przez p,

p(8)  //automatic dereferencing of p 
(*p)(8) //manual dereferencing of p 
+0

Twoja odpowiedź ma sens. ale w książce ** C++ primer 5th edition ** i wielu innych tutorialach na stronie mówiło, że używając nazwy funkcji jako rvalue skonwertuje ją do wskaźnika. Tak więc nie wiem, czy twoja odpowiedź jest szczególnym warunkiem przydziału wskaźnika funkcji. – sydridgm

+0

@sydridgm Są poprawne. I w mojej odpowiedzi odnoszą się do rozpadu funkcji do wskaźnika. – downhillFromHere

Powiązane problemy