Sunteți pe pagina 1din 6

Funcţii

Ce este o funcţie?
O funcţie este un grup de instrucţiuni apelabil (invocabil) din alte părţi ale programului. De
exemplu, main este o funcţie.
A apela o funcţie înseamnă a o executa.
Funcţiile ajută la modularizarea programului, la structurarea acestuia în unităţi logice.
O funcţie se declară în felul următor:

tip nume(lista_param); // Prototipul functiei


Exemplu:
int suma(int a, int b);
lista_param - lista de parametri, despărţiţi prin virgulă, este opţională.
Parantezele sunt obligatorii. Ele deosebesc funcţiile de alte entităţi C++ (de exemplu, variabile).
void nimic(); // functie fara parametri
Tipul void reprezintă absenţa tipului. Cu alte cuvinte, funcţiile care nu returnează nicio valoare,
au tipul void.
Funcţiile pot returna valori codului apelant (locul de unde a fost apelată funcţia) prin intermediul
instrucţiunii return.
După declarare, o funcţie trebuie definită undeva în program.
#include <iostream>
using namespace std;

int suma(int, int); // Declarare

int main()
{
int x, y;
cout << "Da-mi doua numere intregi: ";
cin >> x >> y;
cout << "Suma lor este " << suma(x, y);
return 0;
}

int suma(int a, int b) // Definire


{
int rezultat = a + b;
// Puteam scrie direct
// return a + b;
return rezultat;
}
Când declaraţi o funcţie, puteţi omite numele parametrilor (aşa cum am făcut în exemplu), dar
trebuie să precizaţi tipul lor.
Parametrii sunt variabile locale funcţiei (vizibile numai în blocul funcţiei).
Instrucţiunea return întrerupe execuţia funcţiei şi returnează valoarea expresiei, din dreapta,
codului apelant.
Într-o funcţie puteţi avea mai multe instrucţiuni return.
Observaţi cum se apelează o funcţie: suma(x, y);. Dacă funcţia nu are parametri, se apelează
doar cu nume + paranteze: funcFaraParam();.
Când execuţia unei funcţii se termină, controlul programului revine în punctul apelării şi
programul îşi continuă execuţia normal.
Funcţiile void nu returnează valori, ele doar îndeplinesc o sarcină, deci nu pot avea instrucţiunea
return expr;.
Puteţi însă folosi return; ca să întrerupeţi execuţia unei funcţii void.
#include <iostream>
using namespace std;

void afiseazaText() // Declarare + Definire


{
for (int i = 0; i < 5; i++)
cout << "Hello functions!";
}

int main()
{
// Se va afisa de 5 ori textul:
// Hello functions!
afiseazaText();
return 0;
}
Puteţi declara şi defini o funcţie în acelaşi loc, dar numai înainte de main, altfel compilatorul nu
va recunoaşte funcţia.
Funcţiile void nu pot fi folosite în expresii, deoarece expresiile au în componenţa lor operatori
care aşteaptă valori, ori o funcţie void nu returnează nicio valoare.
O funcţie poate avea orice număr de parametri.
Variabilele declarate într-o funcţie sunt locale, adică sunt vizibile numai în respectiva funcţie.
Ele nu pot fi folosite în afara ei (valabil şi pentru parametri).
Argumentele funcţiei sunt datele (variabile, expresii, constante, etc.) transmise funcţiei şi primite
de parametrii acesteia.
De exemplu, în apelul suma(x, y); argumentele sunt variabilele x şi y.

Parametrii unei funcţii pot avea valori implicite (default). Parametrii default trebuie poziţionaţi la
sfârşitul listei de parametri.
După ce aţi declarat un parametru implicit, nu mai aveţi voie să declaraţi parametri normali în
continuare acestuia, ci doar parametri impliciţi.

#include <iostream>
using namespace std;

double arieCerc(double raza, double PI = 3.14)


{
return 2 * PI * raza * raza;
}

int main()
{
cout << "Aria cercului de raza 2 este " << arieCerc(2.0) << '\n'; // PI
== 3.14
cout << "Aria cercului de raza 2 este " << arieCerc(2.0, 3.141592);
return 0;
}
Se va afişa
Aria cercului de raza 2 este 25.12
Aria cercului de raza 2 este 25.1327
Când nu transmiteţi o valoare parametrului implicit, compilatorul va folosi valoarea implicită,
dată de voi.

Transmiterea prin valoare şi prin referinţă


Atunci când transmiteţi argumente (şi sunt variabile) unei funcţii, transmiteţi de fapt o copie a
acelor variabile.
Aceasta este transmiterea prin valoare (pass by value).
Orice modificare a parametrilor unei funcţii este vizibilă numai în acea funcţie.
Variabilele - folosite ca argumente - rămân nemodificate.

#include <iostream>
using namespace std;

void modifica(int a)
{
a = a + 5;
cout << "a are valoarea: " << a << '\n';
}

int main()
{
int x = 1;
cout << "x inainte de apel: " << x << '\n';
modifica(x);
cout << "x dupa apel: " << x;
return 0;
}
Output:
x inainte de apel: 1
a are valoarea: 6
x dupa apel: 1
O funcţie poate returna decât o singură valoare printr-un return, ca la matematică.
Uneori vrem ca o funcţie să poată returna mai multe valori. Un mod prin care putem obţine acest
lucru este transmiterea prin referinţă (pass by reference).
Atunci când transmiteţi prin referinţă, parametrii funcţiei alterează direct conţinutul variabilelor
argumente (nu mai există nicio copie).
Ca să transmiteţi prin referinţă folosiţi ampersand (&) între tipul parametrului şi numele acestuia.
Parametrii referinţă acceptă numai variabile. NU acceptă constante (deoarece nu pot fi alterate)!
#include <iostream>
using namespace std;

void modifica(int& a) // Nu uitati de ampersand !


{
a = a + 5;
cout << "a are valoarea: " << a << '\n';
}

int main()
{
int x = 1;
cout << "x inainte de apel: " << x << '\n';
modifica(x);
cout << "x dupa apel: " << x;
return 0;
}
Output:
x inainte de apel: 1
a are valoarea: 6
x dupa apel: 6

Vectorii se transmit prin referinţă!

#include <iostream>
using namespace std;

void modifica(int v[], int l)


{
for (int i = 0; i < l; i++)
v[i] += 5; // v[i] = v[i] + 5;
}

int main()
{
int w[] = {1, 2, 3, 4}, k = 4;
modifica(w, k);

for (int i = 0; i < k; i++)


cout << w[i] << ' ';

return 0;
}
Output:
6 7 8 9
Observaţi cum se transmite un vector ca parametru.
Numărul de elemente poate lipsi (valabil doar pentru prima dimensiune).
Dacă aş fi avut o matrice de 2 x 3, atunci aş fi scris:
void modifica(int v[][3], ...) ...
Veţi înţelege mai bine aceste lucruri după ce veţi învăţa ceva despre pointeri.

Funcţii recursive
O funcţie care se autoapelează se numeşte recursivă.
Aveţi grijă ca funcţia să aibă o condiţie de terminare, altfel puteţi crea o repetiţie infinită.
Parametrii funcţiilor şi variabilele locale sunt încărcate, stocate, pe Stivă (o regiune din memorie
structurată pe principiul stivei, LIFO), iar în cazul unei funcţii recursive infinite, Stiva se poate
umple repede (stack overflow) cauzând un crash al programului.
Factorialul unui număr poate fi calculat cu o funcţie recursivă (deşi se poate face acelaşi lucru şi
cu un loop).

#include <iostream>
using namespace std;

int fact(int n)
{
if (n == 0) // Conditia de terminare
return 1;
else
return n * fact(n - 1);
}

int main()
{
cout << fact(0) << '\n';
cout << fact(3) << '\n';
cout << fact(8) << '\n';
return 0;
}
Output:
1
6
40320
Ca să înţelegeţi mai bine mecanismul recursivităţii vizionaţi acest clip de pe Youtube:

Funcţii inline
Atunci când o funcţie este apelată, parametrii şi variabilele locale sunt încărcate pe Stivă.
Acest proces consumă resurse şi timp de execuţie.
Pentru funcţiile ce efectuează puţine operaţii, apelarea poate costa mai mult timp şi spaţiu de
execuţie decât dacă aceste operaţii ar fi executate direct în cod.
Din acest motiv există keyword-ul inline.
Cu inline programatorii pot cere compilatorului să insereze blocul funcţiei în punctul apelării,
în loc să creeze instrucţiunile de apel.
O funcţie se declară inline în felul următor:

#include <iostream>
using namespace std;

inline double myPI()


{
return 3.14159265359;
}

int main()
{
cout << myPI();
return 0;
}
Nu declaraţi inline funcţii recursive sau funcţii complexe!
Mărimea programului poate creşte considerabil.
Compilatoarele moderne de astăzi optimizează automat codul sursă.
Unele dintre ele vor refuza inline, chiar dacă programatorul le cere explicit (de exemplu,
compilatoarele care optimizează mărimea programului), altele vor face automat inline anumite
funcţii (compilatoarele optimizate pentru viteză), chiar dacă programatorul nu cere acest lucru.

S-ar putea să vă placă și