Cum functioneaza apelarea unei functii?
Cand programul intalneste un apel de functie (de ex. salutare();), se intampla 3 lucruri:
1. Programul pune un semn unde a ramas (isi noteaza pozitia curenta)
2. Sare la codul functiei apelate si il executa linie cu linie
3. Cand functia se termina, se intoarce exact la locul marcat si continua de acolo
Citesti o carte (main). La pagina 50 scrie "vezi Anexa B". Pui un semn de carte la pagina 50, mergi la Anexa B, o citesti, apoi te intorci la pagina 50 si continui. Daca in Anexa B scrie "vezi Nota 3", pui un ALT semn de carte in Anexa B, mergi la Nota 3, o citesti, te intorci in Anexa B, termini, si apoi te intorci la pagina 50.
Exemplu simplu: main cheama o functie
Sa urmarim exact ce se intampla cand rulam acest program:
| Pas | Ce se executa | Output | Unde suntem |
|---|---|---|---|
| 1 | Linia 1: cout << "Inainte" | Inainte | in main() |
| 2 | Linia 2: salut(); → SALT! | - | main() → salut() |
| 3 | Linia B: cout << "Salut!" | Salut! | in salut() |
| 4 | salut() se termina → INAPOI | - | salut() → main() |
| 5 | Linia 3: cout << "Dupa" | Dupa | in main() |
Output final: Inainte apoi Salut! apoi Dupa
Ce este Call Stack-ul?
Calculatorul tine o stiva (stack) cu functiile active. Cand apelezi o functie, o pune deasupra stivei. Cand functia se termina, o scoate de pe stiva. Functia din varful stivei este cea care ruleaza acum.
Gandeste-te la o stiva de farfurii: pui o farfurie deasupra (apel) si o scoti de deasupra (return). Ultima pusa = prima scoasa.
Construim comportament complex din piese simple
Puterea functiilor sta in faptul ca le poti combina. O functie poate chema oricata alta functie. Asta iti permite sa construiesti programe complexe din bucati mici, usor de inteles.
O functie poate sa se apeleze pe ea insasi!
Aceasta tehnica se numeste recursivitate. Functia se cheama pe sine, dar de fiecare data cu o valoare diferita. Trebuie sa aiba o conditie de oprire, altfel ruleaza la infinit!
Apel 1
Apel 2
Apel 3
Apel 4 (STOP)
La n=0, conditia de oprire se activeaza. Stiva incepe sa se goleasca: fiecare functie se intoarce la cea de dedesubt.
Daca uiti conditia de oprire, functia se cheama pe sine la infinit. Stiva creste si creste pana cand... CRASH! Eroarea se numeste "stack overflow" (stiva a dat pe-afara). Programul se opreste fortat.
Rezultatul unei functii ca argument pentru alta
Poti folosi valoarea returnata de o functie direct ca argument pentru alta functie. Se evalueaza de la interior spre exterior (ca in matematica).
Pasul 1: Se evalueaza triplu(2) = 2 * 3 = 6
Pasul 2: Rezultatul (6) devine argument: dublu(6) = 6 * 2 = 12
Fiecare functie are propriile variabile
Variabilele declarate in interiorul unei functii sunt locale - ele exista DOAR in acea functie. Cand functia se termina, variabilele dispar. Alte functii nu le pot accesa.
Regula: Defineste inainte de a apela
In C++, compilatorul citeste codul de sus in jos. Daca apelezi o functie care nu a fost inca definita, primesti eroare. Solutia: scrie functia deasupra lui main, sau foloseste un prototip.
Prototipurile sunt utile cand ai mai multe functii care se cheama reciproc, sau cand vrei ca main() sa fie primul lucru pe care il citesti in fisier. In programe mici, e suficient sa definesti functiile deasupra lui main.