Overloaded функции

Overloaded-оптоварена, преклопена функција се добива кога во иста програма се дефинираат неколку функции со исто име, но различни листи на параметри/аргументи. Компајлерот за време на преведувањето (compile-time) одлучува која функција ќе ја повика врз основа на аргументите што се проследени.

int myFunction(int x)
float myFunction(float x)
double myFunction(double x, double y)

Следниов пример има 2 функции за собирање на 2 броја од различен тип


int plusFuncInt(int x, int y) {
  return
 x + y;}

double plusFuncDouble(double x, double y) {
  return
 x + y;}

int main() {
  int
 myNum1 = plusFuncInt(8, 5);
  double
 myNum2 = plusFuncDouble(4.3, 6.26);
  cout << "Int: "
 << myNum1 << "\n";
  cout << "Double: "
 << myNum2;
  return
 0;
}
Наместо да дефинираме 2 функции ќе работиме со преоптоварени функции . Во примерот подолу, ја преоптоваруваме функцијата plusFunc за да работи и за int и за double:

int plusFunc(int x, int y) {
  return
 x + y;}

double plusFunc(double x, double y) {
  return
 x + y;}

int main() {
  int
 myNum1 = plusFunc(8, 5);
  double
 myNum2 = plusFunc(4.3, 6.26);
  cout << "Int: "
 << myNum1 << "\n";
  cout << "Double: "
 << myNum2;
  return
 0;
}

Кога во иста област на важење има повеќе преклопени функции, за функциите со исто име освен првата, преведувачот ја толкува декларацијата на следниов начин:

1.       Ако листите на аргументи се разликуваат по типот или по бројот на параметри , функциите се преклопени.

1. Example 1: Overloading Using Different Types of Parameter пример

#include <iostream>
#include <string>
using namespace std;

// 1. Верзија за целобројни вредности (int)
void prikazi(int broj) {
 cout << "Повикана е верзија со цел број (int): " << broj << endl;}
// 2. Верзија за реални/децимални броеви (double)
void prikazi(double broj) {
cout << "Повикана е верзија со децимален број (double): " << broj << endl;}
// 3. Верзија за текстуални низи (string)
void prikazi(string tekst) {
 cout << "Повикана е верзија со текст (string): \"" << tekst << "\"" << endl;}

int main() {
    // Повици со различни типови на параметри
    prikazi(42);           //  (int)    -> ја повикува верзијата 1
    prikazi(3.14159);      //  (double) -> ја повикува верзијата 2
    prikazi("Здраво C++"); //  (string) -> ја повикува верзијата 3
    return 0;}
Анализа

Исто име: Сите три функции се викаат prikazi.
Различен тип: Првата прима int, втората double, а третата string.
Compile-time одлука: Компајлерот уште за време на преведувањето на кодот
точно знае која функција да ја поврзе за секој повик според типот на аргументот.

Example 2: Overloading Using Different Number of Parameters
#include <iostream>
using namespace std;

// 1. Верзија со 2 параметри
int presmetajZbir(int a, int b) {
 cout << "[Повикана е верзија со 2 параметри] ";
 return a + b;}
// 2. Верзија со 3 параметри
int presmetajZbir(int a, int b, int c) {
 cout << "[Повикана е верзија со 3 параметри] ";
 return a + b + c;}
// 3. Верзија со 4 параметри
int presmetajZbir(int a, int b, int c, int d) {
  cout << "[Повикана е верзија со 4 параметри] ";
  eturn a + b + c + d;}

int main() {
    // Повикување на функциите со различен број на аргументи
 cout << "10 + 20 = " << presmetajZbir(10, 20) << endl;
cout << "10 + 20 + 30 = "<< presmetajZbir(10, 20, 30) << endl;
cout << "10 + 20 + 30 + 40 = " << presmetajZbir(10, 20, 30, 40) << endl;
return 0;}
Анализа

Исто име: Сите три функции го делат истото име presmetajZbir.
Различен број параметри:
Првата дефиниција има 2 параметри: (int a, int b)
Втората дефиниција има 3 параметри: (int a, int b, int c)
Третата дефиниција има 4 параметри: (int a, int b, int c, int d)
Како одлучува компајлерот? Кога во main() ќе напишеме presmetajZbir(10, 20, 30),
компајлерот ги брои аргументите (вкупно 3) и ја поврзува точно втората дефиниција.


2. Ако типот на функциите и листите на аргументи се идентични, втората декларација ја  смета за повторна декларација на функцијата.

       3. Ако листите на аргументи се идентични, а типот на функциите се различни, втората     декларација ја смета за погрешна декларација на функцијата и се јавува грешка.

Parameters should have a different type

add(int a, int b)
add(double a, double b)

#include <iostream>
using namespace std;
  
void add(int a, int b)
{
  cout << "sum = " << (a + b);}
 
void add(double a, double b)
{
    cout << endl << "sum = " << (a + b);}

int main()
{
    add(10, 2);
    add(5.3, 6.2);
     return 0;
}

Parameters should have a different number

add(int a, int b)
add(int a, int b, int c)

#include <iostream>
using namespace std;
 
void add(int a, int b)
{
  cout << "sum = " << (a + b);}
 
void add(int a, int b, int c)
{
    cout << endl << "sum = " << (a + b + c); }
 

// Driver code
int main()
{
    add(10, 2);
 
    add(5, 6, 4);
  
    return 0; } 

Parameters should have a different sequence of parameters

add(int a, double b)
add(double a, int b)

#include<iostream>
using namespace std;
void add(int a, double b)
{
cout<<"sum = "<<(a+b); } 
 

void  add(double a, int b)
{
cout<<endl<<"sum = "<<(a+b); } 

 
// Driver code
int main()
{
    add(10,2.5);
     add(5.5,6);
  
   return 0; } 
// CPP Program to demonstrate that function overloading
// fails if only return types are different
#include <iostream>
int fun() { return 10; }

char fun() { return 'a'; }
// compiler error as it is a new declaration of fun()

int main()
{
char x = fun();
return 0;
}

Output
 In function ‘char fun()’{ return 'a'; }
^
old declaration ‘int fun()’
int fun() { return 10; }
^

Function overloading може да се разликува според бројот или типовите на параметрите, но не само според return type.

Причината е што при повикот fun() компајлерот ја гледа  листата на аргументи за да избере функција, а не го користи типот на променливата во која ќе го зачуваш резултатот за да избере overload.

Резиме 

How the parameters list can be different?

Above are the signatures of the different ‘add’ functions. Now let us check which is valid or which is invalid.

  • int add(int, int) is valid, it is taking 2 ‘int’ type parameters and return ‘int’ value.
  • float add(float, float) is valid as it is taking 2 ‘float’ parameters and return the ‘float’ value. It is taking the same number of parameters but different data types as compared to the first one.
  • int add(int, int, int) is valid as it is taking 3 ‘int’ parameters and return ‘int’ value. It is taking a different number of parameters but has the same data types as compared to the first one.
  • float add(int, int) is invalid, it is the same as the first function which is both the function taking the same number of parameters and the same type of parameters. So, this is invalid. It doesn’t matter what type of data a function is returning. If two functions have the same number of parameters and of the same types then this is invalid.

Услови за валидно преоптоварување

За компајлерот да ги разликува функциите со исто име, мора да постои разлика во нивниот запис:

  1. Различен број на параметри.

  2. Различен тип на параметри.

  3. Различен редослед на типовите на параметрите.

Важно правило: Разликата само во типот на вратена вредност (return type) НЕ е доволна за преоптоварување и тоа предизвикува грешка при компајлирање.

Задача : Преоптоварување на функции (Правилна и неправилна употреба)

Барање: Да се дефинираат функции со име plostina за пресметка на плоштина на квадрати и правоаголници, и да се анализираат исправните и неисправните дефиниции.

#include <iostream>
using namespace std;

// 1. ПРАВИЛНО: Различен број на параметри (квадрат vs правоаголник)
double plostina (double a) {
    return a * a; }

// 2. ПРАВИЛНО: Различен број на параметри
double plostina (double a, double b) {
    return a * b; }

// 3. ПРАВИЛНО: Различен тип на параметри (целобројна верзија)
int plostina (int a, int b) {
    return a * b; }

/* 
// 4. НЕПРАВИЛНО (Грешка при компајлирање!):
// Разлика само во вратениот тип, а параметрите (double, double) се исти со функција 2.
int plostina (double x, double y) {
  return x * y; // Error: 'int plostina (double, double)' conflicts with 'double plostina (double, double)'  }
*/

int main() {
cout<< "Плоштина на квадрат (страна 4.5): " << plostina (4.5) << endl; // Повикува (1)
cout<<"Плоштина на правоаголник (3.5 x 2.0): " << plostina(3.5, 2.0) << endl; // Повикува (2)
cout << "Плоштина со цели броеви (3 x 4): " << plostina (3, 4) << endl; // Повикува (3)
return 0; }