jest fragmentem programu (podprogram), realizującym określone zadanie, który możemy wielokrotnie wywoływać z różnych miejsc programu.
Funkcje dzielimy na:
niezwracające wartości (typ void przed nazwą funkcji; odpowiedniki procedur np. w Pascalu)
zwracające wartość
Funkcja przed zastosowaniem musi być zdefiniowana, a następnie wywołana.
Definicja funkcji składa się z:
nagłówka składającego się z: typu wyniku, nazwy funkcji, listy argumentów zawartych między nawiasami (nie są konieczne, gdy funkcja nie ma argumentów, po jej nazwie pozostawiamy puste nawiasy) oddzielonych przecinkami np. typ_wyniku nazwa_funkcji (typ argument1, typ argument2)
treści składającej się z: instrukcji zawartej między klamrami np. {return argument1 + argument 2} //return jeśli funkcja zwraca wartość
Wywołanie funkcji polega na wpisaniu jej nazwy w odpowiednim miejsu funkcji głównej main i wprowadzeniu parametrów aktualnych (zmienne, wyrażenia, konkretne wartości) w miejsce parametrów formalnych. Gdy funkcja nie ma argumentów pozostawiamy puste nawiasy.
nazwa_funkcji (lista_argumentów_aktualnych) lub w przypadku funkcji bez argumentów nazwa_funkcji ()
Sposoby definiowania i wywoływania funkcji:
całą definicję (nagłówek i treść) umieszczamy przed funkcją główną main; wywołujemy wpisując w funkcji głównej jej nazwę wraz z przekazywanymi do funkcji wartościami,
deklarujemy funkcję (tzw. prototyp funkcji) - tj. określamy sam nagłówek zakończony średnikiem przed funkcją główną main; po deklaracji możemy już wywoływać naszą funkcję wewnątrz innej; definicję umieszczamy w dowolnym miejscu programu - w praktyce czytelnie gdy po funkcji main (wygodne przy większej liczbie funkcji);
z użyciem oddzielnego pliku ( biblioteki) z rozszerzeniem *.h
Lista argumentów znajdująca się w definicji i deklaracji funkcji nazywana jest listą argumentów formalnych, a argumenty argumentami formalnymi. Argumenty przekazane do funkcji w momencie jej wywołania, które mogą przyjmować różną wartość, nazywamy argumentami aktualnymi.
typ_wyniku nazwa_funkcji (lista_argumentów)
{
instrukcje;
return zwracana_wartość;
}
typ_wyniku - tj. typ zwracanej wartości, określa rodzaj informacji, którą zwraca funkcja jako wynik (np. obliczeń, do wykorzystania przez inne części programu). Do zwracania wyniku służy instrukcja return (jeśli zwraca wartość 0 to typ int). Jeśli funkcja nie zwraca wyniku (np. wykonuje tylko kod) to posiada typ void (ang. pusty).
nazwa_funkcji - umożliwia odwołanie się do jej kodu, reguły tworzenia nazwy funkcji takie jak przy nazwach zmiennych),
lista_argumentów - (inaczej: lista parametrów formalnych) zawiera nazwy zmiennych wraz z ich typami przekazywane do funkcji (typ_argumentu1 nazwa_argumentu1, typ_argumentu2 nazwa_argumentu2, …) oddzielone przecinkami,
typ_argumentu - np. int, double, bool lub zdefiniowany przez użytkownika.
nazwa_argumentu - pozwala odwoływać się do danego argumentu wewnątrz funkcji.
instrukcje do wykonania przez funkcje wpisywane są w nawiasach kamrowych {}
Przykład. Funkcja zwracająca wartość
#include <cstdlib>
#include <iostream>
using namespace std;
int suma(int a, int b) {
return a+b;
}
int main()
{
cout << "5 + 10 = ";
cout << suma(5,10) << endl;
system("PAUSE");
return 0;
}
Komentarz
Definiujemy funkcje: nazwa suma (typ całkowity) do której będziemy przekazywać 2 liczby całkowite, stąd zwracany wynik też będzie całkowity. Argumenty są tego samego typu, ale błędem byłby zapis (int a,b).
W nawiasach klamrowych (ciało funkcji) umieszczamy instrukcje do wykonania przez funkcje suma umieszczając słowo kluczowe return i wyrażenie, przez co funkcja zwróci sumę przekazanych liczb
W funkcji głównej umieszczamy wywołanie, przekazując jako argumenty liczby 5 i 10
Przykład. Program z funkcją niezwracającą wartości i bez argumentów
#include < iostream >
#include < cstdlib >
using namespace std;
void powitanie()
{
cout << "Witaj świecie" << endl;
}
int main(int argc, char** argv) {
powitanie();
return 0;
}
Komentarz
Słowo kluczowe void przed nazwą funkcji, informuje, że funkcja nie zwraca żadnej wartości.
Funkcja ta dodatkowonie nie przyjmuje żadnych argumentów, bo wewnątrz nawiasów pusto.
Wewnątrz klamr (blok instrukcji; ciało funkcji) umieszczamy kod do wykonania, gdy funkcja zostanie wywołana
Wywołując funkcję nie zwracającą wartości, wpisujemy jej nazwę w odpowiednim miejscu w programie (np. funkcji głównej main): nazwa_funkcji
W przypadku funkcji z argumentami dodatkowo podajemy parametry aktualne: nazwa_funkcji(lista parametrów aktualnych)
Przykład. Program z funkcją niezwracającą wartości z argumentem
#include < iostream >
#include < cstdlib >
using namespace std;
int m
void powitanie(int n)
{
cout << "Witaj świecie" << endl;
}
int main(int argc, char** argv) {
cin >> m
powitanie(m);
return 0;
}
Komentarz
n - argument formalny (nie wymaga oddzielnego deklarowania, gdyż jego typ określony w deklaracji funkcji - traktowany jak zmienna lokalna)
m - argument aktualny
Wywołując tę funkcję w miejsce argumentu formalnego wprowadzimy argument aktualny.
Zasięg zmiennej określa zakres widoczności nazwy zmiennej w obrębie programu.
Ze względu na zasięg zmiennej rozróżniamy:
zmienne globalne - deklarujemy poza funkcjami i są one widoczne w całym programie
zmienne lokalne - deklarujemy wewnątrz funkcji i widoczne są od miejsca deklaracji do końca funkcji; są widoczne tylko w obrębie jednego bloku instrukcji { }.
Jeżeli w różnych funkcjach istnieją zmienne o takich samych nazwach, to są to różne zmienne i nie wpływają na siebie nawzajem.
Zmienna globalna zostanie przesłonięta przez zmienną lokalną (widoczna będzie lokalna) wtedy, gdy w funkcji zostanie zadeklarowana zmienna o takiej samej nazwie jak zmienna globalna.
Przekazywanie argumentów przez wartość
do funkcji przekazywane są (“kopiowane”) wartości argumentów aktualnych (“ich orginały” nie ulegają zmianie), które - podczas wykonania operacji na odpowiadających im argumentach formalnych wewnątrz funkcji - nie ulegają zmianie,
operacje wykonywane na argumentach wewnątrz funkcji, nie wpływają na stan zmiennych poza funkcją (argumenty traktowane są jako zmienne lokalne), stąd przekaz przez wartość jest bezpieczny, ale wymaga kopiowania danych przy każdym wywołaniu funkcji (mało wydajne).
Deklaracja funkcji z przekazywaniem argumentów przez wartość:
typ_rezultatu_funkcji nazwa_funkcji (lista argumentów)
Przekazywanie argumentów przez zmienną (referencję)
do funkcji przekazywane są ("orginały") argumenty aktualne, które - w momencie użycia odpowiadających im argumentów formalnych - ulegają zmianie,
w razie modyfikacji argumentu w funkcji zmianie ulegają dane znajdujące się poza nią, stąd przekaz przez referencję jest wydajniejszy, ale niebezpieczny (gdy taka zmiana niepożądana, można na liście argumentów stosować modyfikatory const, uniemożliwiające zmianę wartości argumentu wewnątrz funkcji)
Deklaracja funkcji z przekazywaniem argumentów przez zmienną (referencję):
typu_rezultatu_funkcji nazwa_funkcji (nazwa_typu &argument)
W deklaracji funkcji przed nazwa argumentu należy użyć znaku &
Przykład. Przekazywanie argumentów przez wartość.
#include <iostream>
using namespace std;
void zwieksz(int x)
{
x = x+5; //zwiększamy argument o 5; krótszy zapis x += 5
cout << x << endl; //wartość arg. formalnego po modyf.
}
int main()
{
int a;
a = 10;
cout << a << endl;
zwieksz(a); // wywołanie funkcji
cout << a << endl;
return 0;
}
Komentarz
Po uruchomieniu programu otrzymamy:
10 //argument aktualny przed wywołaniem
15//argument formalny po modyfikacji przez funkcję
10//argument aktualny po wywołaniu przez funkcję
Wywołując funkcję w miejsce argumentów formalnych np. x, y, przekazujemy wartość liczbową zmiennych a, b (argumenty aktualne; kopiowana jest ich wartość). Zmienne te (x i odpowiadająca mu a …) zajmują oddzielne miejsce w pamięci komputera, stąd działania na wartościach zmiennych x, y nie mają wpływu na wynik wywołania funkcji z argumentami a, b. Wartość zmiennych a,b zarówno na początku jak i na końcu wykonywania funkcji nie ulega zmianie.
Przykład. Przekazywanie argumentów przez zmienną (referencję).
#include <iostream>
using namespace std;
void zwieksz(int &x)
{
x = x+5; //zwiększamy argument o 5; krótszy zapis x += 5
cout << x << endl; //wartość arg. formalnego po modyf.
}
int main()
{
int a;
a = 10;
cout << a << endl;
zwieksz(a); // wywołanie funkcji
cout << a << endl;
return 0;
}
Komentarz
Po uruchomieniu programu otrzymamy:
10 //argument aktualny przed wywołaniem
15//argument formalny po modyfikacji przez funkcję
15//argument aktualny po wywołaniu przez funkcję