Funkcje
Spis treści
1 Podstawowe informacje
1.1 Przykłady
2 Wywoływanie funkcji
2.1 Przykład
3 Funkcje rekurencyjne
4 Funkcje inline
5 Przeładowanie nazwy funkcji
W programowaniu mianem funkcji określa się fragment kodu, który może być wykonywany wielokrotnie z różnych miejsc programu.
Podstawowe informacje
Ogólny zapis funkcji wygląda tak:
typ nazwa(argumenty)
{
ciało funkcji
}
{
ciało funkcji
}
Typ określa, jaki typ danych zwraca ta funkcja, tzn. do zmiennej jakiego typu można przypisać wynik funkcji. Funkcja może nie zwracać żadnego typu, wtedy jej typem jest Void - jeśli znasz Pascala łatwiej Ci to będzie porównać do procedur. Do zwracania danej wartości przez funkcję odpowiada słowo kluczowe return. Nazwa służy do identyfikowania funkcji w programie. Nazwa funkcji nie zawsze jednoznacznie identyfikuje funkcję. Argumenty określają, jakiego typu zmienne należy przekazać do funkcji przy jej wywoływaniu. W przypadku, kiedy nazwa nie identyfikuje jednoznacznie funkcji (istnieją dwie różne funkcje o tych samych nazwach), parametry tych funkcji muszą się różnić. Mamy wtedy doczynienia z przeładowaniem nazwy funkcji (patrz niżej). Argumenty funkcji mogą przyjmować wartości domyślne. Należy w takim przypadku po nazwie argumentu dodać znak równości i wartość domyślną. Ciało funkcji jest to kod, który zostanie wykonany po wywołaniu funkcji.
Przykłady
Funkcja nie zwracająca wyniku, nie przyjmująca argumentów (typu Void):
Funkcja nie zwracająca wyniku, przyjmująca parametr bez wartości domyślnych:
Funkcje zwracająca wynik, przyjmująca parametry bez wartości domyślnych:
Funkcja zwracająca wynik, przyjmująca parametry z wartością domyślną:
Wywoływanie funkcji
Aby wywołać w programie przygotowaną wcześniej funkcję, należy po prostu wpisać w odpowiednim miejscu jej nazwę, a w nawiasach okrągłych argumenty do tej funkcji. Wywoływana funkcja musi zawsze być zadeklarowana przed miejscem, gdzie została wywołana. Można przed wywołaniem funkcji napisać tylko jej deklarację, zaś definicję (ciało) w dowolnym miejscu programu.
W językach C/C++ jeśli funkcja nie posiada argumentów należy ją wywoływać stawiając za jej nazwą pusty nawias, np foo()
Przykład
#include <iostream>
using namespace std;
int foo(int a, int b); // Deklaracja funkcji
int main()
{
int a;
cin >> a;
int b = foo(a, 5);
cout << b << endl;
return 0;
}
int foo(int a, int b)
{
return a+b;
}
using namespace std;
int foo(int a, int b); // Deklaracja funkcji
int main()
{
int a;
cin >> a;
int b = foo(a, 5);
cout << b << endl;
return 0;
}
int foo(int a, int b)
{
return a+b;
}
Funkcje rekurencyjne
Funkcje rekurencyjne są to funkcje wywołujące same siebie. Może się to wydać na pierwszy rzut oka dziwne. Ten typ funkcji należy omówić na przykładzie. Jedną z takich funkcji rekurencyjnych będzie funkcja obliczających silnię z liczby. Definicja silni wygląda następująco:
0 != 1;
n != (n-1)!*n;
n != (n-1)!*n;
Jeśli rozpiszemy ten wzór, szybko się przekonamy, że silnia to po prostu iloczyn kolejnych liczb mniejszych od tej liczby i tej liczby. Dlatego pierwszą rzeczą jaką trzeba zrobić jest szkielet funkcji:
Na dalszym etapie trzeba mieć opanowane instrukcje warunkowe. Następnym etapem jest sprawdzenie, czy argument n nie jest równy 0. Jeśli jest, można od razu zwrócić wartość (1):
Jeśli wartość jeszcze nie została zwrócona (a tym samem funkcja nie przerwała działania), oznacza to, że n jest różne od 0. Wyliczmy wtedy wartość silni ze wcześniej podanego wzoru:
Aby sprawdzić, czy funkcja rzeczywiście działa, napiszmy prosty program korzystający z niej:
#include <iostream>
using namespace std;
int silnia(int n)
{
if(n == 0) return 1;
return silnia(n-1)*n;
}
int main()
{
int a;
cin >> a;
cout << silnia(a) << endl;
return 0;
}
using namespace std;
int silnia(int n)
{
if(n == 0) return 1;
return silnia(n-1)*n;
}
int main()
{
int a;
cin >> a;
cout << silnia(a) << endl;
return 0;
}
Przykładowe wyniki to:
0 != 1;
1 != 1;
2 != 2;
3 != 6;
4 != 24;
10 != 3628800
1 != 1;
2 != 2;
3 != 6;
4 != 24;
10 != 3628800
Funkcje inline
Funkcje inline to mechanizm występujący w C++, podobny do Makrodefinicji z klasycznego C. Polega on na tym, że funkcja nie jest wywoływana, tylko jej zawartość jest "wklejana" w określone miejsce programu. Jest to korzystne dla bardzo małych funkcji - objętość kodu zwiększa się, ale zaoszczędza się czas związany z wywołaniem funkcji.
Przeładowanie nazwy funkcji
Przeładowanie (ang. overloading) nazwy funkcji związane jest z tym, że ma ono więcej niż jedno znaczenie. Ogólnie rzecz biorąc - ta bardzo przydatna cecha języka C++ służy do zadeklarowania (i oprogramowania) kilku funkcji o takiej samej nazwie. To oczywiście nie wszystko. Gdyby cała idea przeładowania nazwy funkcji kończyła się na samej jej nazwie, byłoby to po prostu nielogiczne. Reasumując, możemy zmieniać typy przekazywanych argumentów funkcji, jak również ich ilość oraz typ, który zwraca funkcja (ale zmiana jedynie zwracanego typu bez zmiany listy argumentów nie powoduje przeciążenia funkcji!).
Spójrz na przykład:
int dodaj(int liczba1, int liczba2)
{
return liczba1 + liczba2;
}
double dodaj(double liczba1, double liczba2)
{
return liczba1 + liczba2;
}
{
return liczba1 + liczba2;
}
double dodaj(double liczba1, double liczba2)
{
return liczba1 + liczba2;
}
Powyżej zdefiniowałem dwie funkcje dodaj(), które zostały przeładowane, tj. różnią się listą argumentów (w pierwszej użyto typu Int, w drugiej Double). Przykład z użyciem powyższych funkcji:
int main()
{
cout << dodaj(2, 4) << endl; // wyświetli: 6
cout << dodaj(2.5, 4.5) << endl; // wyświetli: 7
}
{
cout << dodaj(2, 4) << endl; // wyświetli: 6
cout << dodaj(2.5, 4.5) << endl; // wyświetli: 7
}
W pierwszym wypadku wyświetlamy wynik dodawania liczb całkowitych, a potem - za pomocą "tej samej" funkcji - wynik dodawania liczb typu zmiennoprzecinkowego. Jest to przecież wygodniejsze, niż pisanie dwóch funkcji o różnych nazwach, gdyż zmieniamy tylko wartości przekazywane do parametrów, nie grzebiąc w nazwach funkcji. Jest to przydatne szczególnie w większych programach. Oczywiście nic nie stoi na przeszkodzie, aby zmienić ilość argumentów jednej z funkcji (w przytoczonym przykładzie przekazujemy dwa argumenty w obu funkcjach).
W C++ czasami lepiej zastosować Szablony funkcji niż przeładowywanie nazw.
sobol dnia 14-06-2008 09:24
ja bym jeszcze dodal ze silnia moze byc tylko z liczb nieujemnych (dodatnich i zera)
Miczu dnia 12-11-2006 21:37
Funkcje rekurencyjne jak pięknie zrobiona ^^ z tylu zadań z matmy moge pujść na łatwizne...
Kooba dnia 16-08-2006 14:05
Jeszcze warto wspomnieć o funkcjach inline
Coldpeer dnia 01-06-2006 18:34
Nie chodzi przecież o podstawową składnię między C a C++ (pod C++ printf() też pójdzie
), tylko o istotę działania funkcji więc myślę, że można dać sobie z takimi detalami spokój 
), tylko o istotę działania funkcji więc myślę, że można dać sobie z takimi detalami spokój 
Wolverine dnia 01-06-2006 17:07
Nie, chyba, ze w jakis magiczny sposob umiesz korzystac z iostream w C.
Maczugos dnia 01-06-2006 16:35
dotyczy c i c++, nie widać?
Wolverine dnia 01-06-2006 13:19
Nie mozna bylo do Worda tego wkleic?
Poza tym artykul mozna by napisac tak aby dotyczyl i C i C++.
Poza tym artykul mozna by napisac tak aby dotyczyl i C i C++.

