Strona główna » Kursy » Kurs C++ » Przeciążanie funkcji
 

Przeciążanie funkcji

Przeciążenie

Przeładowanie funkcji pozwala na wykonanie tego samego zadanie uwzględniając inny typ danych. Dzięki temu programista nie musi pamiętać różnych aliasów tej samej funkcji. Wystarczy, że pamięta tylko jego nazwę, a program automatycznie rozpoznaje jaki kod wykonać. Przeciążenie pozwala utrzymać kod lepiej zorganizowany, a przede wszystkim pomaga programiście uniknąć użycia niewłaściwego aliasu funkcji.

Przykłady

Dodawanie

Przypuśćmy, że posiadamy funkcję suma(), która przyjmuje dwa argumenty a i b, które są liczbami całkowitymi. Wynikiem działania tego typu funkcji jest również liczba całkowita:

  1. int suma(int a, int b){
  2.   return a + b;
  3. }

Wywołanie funkcji w sposób suma(2, 3) zwróci poprawny wynik 5. Jednak już dla wywołania suma(1.5, 3.5) wyjdzie nie 5, a 4. Można się o tym przekonać dopisując do funkcji suma() poniższy kod:

  1. int main() {
  2.   int a = 3, b = 2;
  3.   cout << suma(a, b) << endl;
  4.   double c = 1.5, d = 3.5;
  5.   cout << suma(c, d) << endl;
  6.   system("pause");
  7.   return 0;
  8. }

Dzieje się tak, ponieważ funkcja jest przygotowana tylko na liczby całkowite. Wszystkie liczby rzeczywiste w trakcie wywołania funkcji suma() są rzutowane na liczby całkowite co skutkuje utratą części ułamkowej jak nawet zmianą wartości części całkowitej. Rozwiązaniem tego problemu mogłoby być zmianę typu int parametrów oraz typu zwracanej wartości w deklaracji funkcji suma(). Jednak takie rozwiązanie oznacza, że nawet dodają dwie liczby całkowite zwrócona zostanie liczba rzeczywista.

Zdecydowanie lepszym pomysłem jest dopisanie przeciążenia funkcji. Innymi słowy funkcja będzie miała swój alias pod tą samą nazwą, ale będzie przyjmować inny typ danych. Przed funkcją suma() należy dopisać poniższy kod:

  1. double suma(double a, double b){
  2.   return a + b;
  3. }

Teraz ponownie testując program można zauważyć, że za każdym razem program zwraca prawidłową wartość.

Zwiększanie wartości

Załóżmy, że w programie jest wbudowana funkcja zwiekszWartosc(). Jednak podawanie za każdym razem o ile jest męczące, ponieważ zwykle korzysta się z tego do zwiększania o 1. W tego typu przypadku można dodać deklarację funkcji jedno oraz dwuargumentową tak jak w poniższym przykładzie:

  1. void zwiekszWartosc(int &a, int d){
  2.   a += d;
  3. }
  4. void zwiekszWartosc(int &a){
  5.   zwiekszWartosc(a, 1);
  6. }

Jeśli podczas wywoływania funkcja zwiekszWartosc() zostaną podane dwa argumenty to zostanie wykonana funkcja (1. - 3.). Jednak jeśli zostanie podany tylko jeden argument to zostanie wywołane (5. - 7.), które wywoła funkcję (1. - 3.) z drugim argumentem 1. Choć powyższe funkcje można zapisać prościej tj. modyfikację a w funkcji jednoargumentowej dokonać bez wywoływania aliasu dwuargumentowego o tyle warto pamiętać, że w przypadku bardziej skomplikowanych funkcji łatwiej będzie zmienić działanie funkcji tylko w jednym miejscu kodu.

Warto też zwrócić uwagę tutaj na kolejność funkcji. O ile w poprzednim przykładzie kolejność nie miała większego znaczenia o tyle w tym przypadku funkcje muszą być tak ułożone, ponieważ druga wersja korzysta z pierwszej. Obowiązuje tu identyczne zasada jak podczas pisania własnych funkcji - korzystać można z funkcji tylko już określonych.

Brak lub wiele odpowiedników

Rozpatrzmy ponownie funkcję suma(). Tym razem zastanówmy się co się stanie w przypadku podania jednej liczby całkowitej i jednej rzeczywistej jako jej argumenty. Okazuje się, że taki program nie powinien się skompilować. Jako błąd kompilator podaje zbyt dużo dopasowań suma(a, b). Rozwiązaniem tego problemu jest albo użycie wartości argumentów o tym samym typie, albo dopisanie dwóch kolejnych przeciążeń funkcji suma:

  1. double suma(double a, int b){
  2.   return suma(a, double(b));
  3. }
  4. double suma(int a, double b){
  5.   return suma(double(a), b);
  6. }

Należy pamiętać, że należy dopisać dla pary typów {int, double} oraz {double, int}. Do tego warto pamiętać, że typ int należy zamienić na double, ponieważ podczas tej zamiany nie zostaną utracone żadne dane co jest możliwe w przypadku zamiany double na int.

Podsumowanie

Lekcja 12 dobiegła końca. Zajrzyj do kodu źródłowego, aby przeanalizować wypisywanie danych jeszcze raz. Następnie spróbuj wykonać zadania, aby utrwalić materiał.

Zadania

Zadanie 1

Zaimplementuj w programie funkcję zwiekszWartosc() o identycznym działaniu jak w artykule. Dopisz do tego przeciążenie funkcji, który pozwala podawać do funkcji dwa argumenty rzeczywiste.

Zadanie 2

Napisz funkcję suma(), która będzie mogła przyjmować dwa lub trzy argumenty, które będą liczbami całkowitymi. Funkcja powinna zwracać sumę podanych argumentów.