MySQL Java JavaScript PHP Python HTML-CSS C-sharp C++ Go

Supraîncărcarea funcțiilor

Limbajul C++ permite definirea funcțiilor cu același nume, dar cu un set diferit de parametri. Această posibilitate se numește supraîncărcarea funcțiilor (function overloading). Compilatorul, în timpul compilării, va alege versiunea necesară a funcției pe baza parametrilor.

Pentru a defini mai multe versiuni ale unei funcții cu același nume, toate aceste versiuni trebuie să difere prin cel puțin unul dintre următoarele criterii:

  • au un număr diferit de parametri
  • parametrii corespunzători au tipuri diferite

Totodată, versiunile funcției pot să difere și prin tipul valorii returnate. Cu toate acestea, compilatorul, atunci când alege ce versiune să folosească, se orientează doar după numărul și tipurile parametrilor.

Să analizăm un exemplu simplu:

#include <iostream>
 
int sum(int, int);
double sum(double, double);
 
int main()
{
    int result1 {sum(3, 6)}; // se alege versiunea int sum(int, int)
    std::cout << result1 << std::endl; // 9
 
     
    double result2 {sum(3.3, 6.6)}; // se alege versiunea double sum(double, double)
    std::cout << result2 << std::endl; // 9.9
}
int sum(int a, int b)
{
    return a + b;
}
double sum(double a, double b)
{
    return a + b;
}

Aici sunt definite două versiuni ale funcției sum, care adună două numere. Într-un caz, ea adună două numere de tip int, iar în celălalt – numere de tip double. La apelul funcției, compilatorul determină pe baza argumentelor transmise ce versiune să utilizeze. De exemplu, la primul apel sunt transmise numere int:

int result1 {sum(3, 6)};

În consecință, pentru acest apel este aleasă versiunea:

int sum(int, int);

În al doilea apel sunt transmise numere cu virgulă mobilă:

double result2 {sum(3.3, 6.6)};

Prin urmare, se alege versiunea care primește numere double:

double sum(double, double);

La fel, versiunile supraîncărcate ale funcției pot diferi și prin numărul de parametri:

#include <iostream>
 
int sum(int, int);
int sum(int, int, int);
 
int main()
{
    int result1 {sum(3, 6)}; // se alege versiunea int sum(int, int)
    std::cout << result1 << std::endl; // 9
 
     
    int result2 {sum(3, 6, 2) }; // se alege versiunea int sum(int, int, int)
    std::cout << result2 << std::endl; // 11
}
int sum(int a, int b)
{
    return a + b;
}
int sum(int a, int b, int c)
{
    return a + b + c;
}

Supraîncărcarea funcțiilor și parametrii de tip referință

La supraîncărcarea funcțiilor cu parametri-referință trebuie să ținem cont de faptul că parametrii de tip data_type și data_type& nu sunt considerați diferiți în contextul supraîncărcării. De exemplu, următoarele două prototipuri:

void print(int);
void print(int&);

Nu sunt considerate versiuni diferite ale funcției print.

Supraîncărcarea și parametrii constanți

La supraîncărcarea funcțiilor, un parametru constant se deosebește de unul neconstant doar în cazul referințelor și pointerilor. În celelalte cazuri, un parametru constant este considerat identic cu cel neconstant. De exemplu, următoarele două prototipuri NU vor fi considerate diferite la supraîncărcare:

void print(int);
void print(const int);

În al doilea prototip, compilatorul ignoră specificatorul const.

Exemplu de supraîncărcare a funcției cu parametri constanți

#include <iostream>
 
int square(const int*);
int square(int*);
 
int main()
{
    const int n1{2};
    int n2{3};
    int square_n1 {square(&n1)};
    int square_n2 {square(&n2)};
    std::cout << "square(n1): " << square_n1 << "\tn1: " << n1 << std::endl;
    std::cout << "square(n2): " << square_n2 << "\tn2: " << n2 << std::endl;
}
 
int square(const int* num)
{
    return *num * *num ;
}
int square(int* num)
{
    *num = *num * *num; // modificăm valoarea la adresa din pointer
    return *num;
}

Aici funcția square primește un pointer către un număr și îl ridică la pătrat. În primul caz, parametrul este un pointer către o constantă, iar în al doilea – un pointer obișnuit.

La primul apel:

int square_n1 {square(&n1)};

Compilatorul va folosi versiunea:

int square(const int*);

deoarece valoarea transmisă, n1, este o constantă. Prin urmare, valoarea transmisă nu va fi modificată în funcție.

La al doilea apel:

int square_n2 {square(&n2)};

Compilatorul va folosi versiunea:

int square(int*);

în care, pentru exemplu, valoarea transmisă este modificată. Astfel, valoarea n2 va fi schimbată în funcție. Afișarea în consolă va fi:

square(n1): 4   n1: 2  
square(n2): 9   n2: 9

Cu transmiterea prin referință constantă totul va fi similar.