2011-08-18 18 views
8

Przepraszam, jeśli zostało to wcześniej zadane, ale nie mogłem go znaleźć.funkcja pass przez wartość (?) Zamiast wskaźnika funkcji?

Próbuję się uczyć o szablonach i nowych funkcjach C++ 11 (głównie lambdas, coś, co zawsze podobało mi się w innych językach).

Ale w moich testach doszedłem do czegoś, nie miałem pojęcia, że ​​pracował, a ja staram się zrozumieć, jak to działa, ale nie mogę zrozumieć to ..

Poniższy kod:

template <class Func> 
void Test(Func callback) { 
    callback(3); 
} 

void Callback(int i) { 
    std::cout << i << std::endl; 
} 

int main(int argc, char** argv) { 
    Test(&Callback); // this I was expecting to work, compiler will see its a pointer to a function 
    Test(Callback); // this also works, but how?! 
    return 0; 
} 

Jeśli rozumiem, jak działają szablony, w zasadzie są one schematem dla kompilatora, który wie, co budować, więc pierwsze wywołanie Test(&Callback); oczekiwałem pracy, ponieważ kompilator zobaczy szablon otrzyma adres funkcji i przyjmie argumenty być wskaźnikiem.

Ale jaki jest drugi telefon? Jaki jest szablon, zakładając, że tak jest? Kopia functio (jeśli to w ogóle ma sens)?

Odpowiedz

14

Funkcja jest niejawnie przekształcalna na wskaźnik do siebie; ta konwersja dzieje się prawie wszędzie. Test(Callback) jest dokładnie taki sam, jak Test(&Callback). Nie ma różnicy. W obu przypadkach Func jest wydedukowany jako void(*)(int).

Wskaźniki funkcji są dziwne. Możesz dowiedzieć się więcej o nich w "Why do all these crazy function pointer definitions all work?"

+0

dzięki za odpowiedź. więc gdybym nie używał szablonów i zadeklarował Test: void Test (void (* callback) (int)) {...} oba połączenia również by działały. dobrze wiedzieć. chory upewnij się, że przeczytałem wątek, który łączyłeś. – sap

3

W C++ funkcje nie są obiektami pierwszej klasy, co oznacza, że ​​"funkcja jako wartość" nie ma w tym żadnego sensu. Dlatego nazwa funkcji zawsze była domyślnie wymienialna na wskaźnik do niej.

+0

Może warto zauważyć, że istnieją języki, w których "funkcjonowanie według wartości" ma sens. – hamstergene

2

Funkcje są niejawnie przekształcalne na wskaźniki funkcji. Jeśli nie ma możliwości uzyskania wartości funkcji lub odniesienia. Chociaż możesz stworzyć typ wartości funkcji, po prostu nie możesz przypisać mu niczego.

Here is code snippit który pokazuje, jak lambdy i różne wywołania zwrotne reagują na szablony.

+0

dzięki za kod, naprawdę pomocne. – sap

+0

To jest złe. Odnośniki funkcji są w porządku. Jeśli 'Test' zostanie zadeklarowany jako' void Test (Func & callback) ', to' Func' zostanie wydedukowane do 'void (int)', a 'Callback' zostanie przekazane jako odniesienie, bez konwersji do wskaźnika, do' Testuj. –

+0

Wow! Myślę, że to ma sens, że referencje powinny być wspierane, a także wskaźniki, ponieważ są one tak podobne. Czy można zadeklarować wartość funkcji i przypisać do niej coś? –

0

W C++ 11 (i boost i tr1) mamy std :: function jako typ szablonu do przechowywania funktorów, lambd i funkcji. Tak więc możesz zdecydowanie mieć pojęcie utrzymania wartości funkcji w zmiennej typu std :: function. ta zmienna może być również "pusta", co oznacza, że ​​nie jest w niej zapisana żadna funkcja (odwołanie). Wtedy nie można go nazwać.

Pierwotne pytanie dotyczy tego, że w odróżnieniu od C, C++ umożliwia odniesienie do funkcji. Ponadto ze względu na kompatybilność z C nazwa funkcji może zostać zwyrodniona do wskaźnika funkcji. Ale z powodu przeciążenia rzeczy są bardziej "interesujące" w C++ niż w C.

Powiązane problemy