Funkcje przeciążone (Function Overloading)

1. Co to jest przeciążanie funkcji?

Przeciążanie funkcji (function overloading) to mechanizm w języku C++, który pozwala tworzyć wiele funkcji o tej samej nazwie, ale:

  • z różnymi parametrami,
  • lub różnymi typami parametrów,
  • lub różną liczbą parametrów.

Kompilator wybiera odpowiednią funkcję na podstawie listy argumentów w momencie wywołania.

➡ Dzięki temu jeden identyfikator funkcji może obsługiwać wiele wariantów tego samego działania.


2. Po co stosuje się przeciążanie funkcji?

Poprawa czytelności

Zamiast:

możemy napisać:

Ujednolicenie interfejsu

Pozwala tworzyć spójne API — ta sama nazwa, różne konteksty.

Lepsza organizacja kodu

Funkcje robią logicznie to samo, więc mają wspólną nazwę.


3. Zasady przeciążania funkcji

Funkcje muszą różnić się sygnaturą, czyli:

  • liczbą parametrów,
  • typem parametrów,
  • kolejnością parametrów.

NIE WOLNO przeciążać funkcji tylko na podstawie typu zwracanego!

To nie działa:


4. Przykłady przeciążania

4.1. Różne typy parametrów


4.2. Różna liczba parametrów


4.3. Różna kolejność typów parametrów


4.4. Przeciążanie z parametrami domyślnymi (uwaga!)

Wywołanie:

→ Niejednoznaczność, bo kompilator nie wie, którą wersję wybrać.


5. Jak kompilator wybiera odpowiednią funkcję? (Overload Resolution)

Procedura wyboru składa się z etapów:

Szukanie kandydatów

  • Wszystkie funkcje o dopasowanej nazwie.

Filtrowanie wykonalnych funkcji

  • Lista argumentów musi pasować po konwersji.

Wybór najlepszego dopasowania

Preferowane są:

  • brak konwersji > konwersja standardowa > konwersja złożona,
  • unikanie rzutowania (castów),
  • unikanie konwersji wielokrotnych.

6. Przykłady z konwersją — uwaga na niejednoznaczność

Przykład niejednoznaczny:

Znak 'a' może być:

  • konwertowany do int,
  • albo do double.

➡ Kompilator wybierze int, bo to lepsze dopasowanie (konwersja integralna).


Bardziej problematyczny przykład:

10 jest typu int → oba są możliwe. Kompilator wybiera wersję z long, ponieważ konwersja int -> long jest lepsza niż int -> double.


7. Częste błędy przy przeciążaniu

1. Przeciążanie tylko przez typ zwracany

Nie działa — typ zwracany nie jest częścią sygnatury.

2. Konflikty z parametrami domyślnymi

3. Niejednoznaczność wywołań

4. Przeciążanie bez sensownej logiki

Trzeba wiedzieć, kiedy to ma sens — nadużywanie przeciążania utrudnia czytelność.


8. Przeciążanie funkcji a funkcje szablonowe

Funkcje szablonowe również mogą być przeciążane:

Jeśli wywołamy:

→ kompilator wybiera wersję konkretną (dla int), bo jest lepszym dopasowaniem niż szablon.


9. Przykład praktyczny — przeciążenie operatora

Przeciążanie funkcji dotyczy również operatorów.

Operator + jest przeciążoną funkcją o specjalnej nazwie.


10. Kiedy warto stosować przeciążanie?

  • Gdy funkcje wykonują to samo, ale przyjmują inne dane.
  • Gdy chcemy uprościć API.
  • Gdy naturalne jest użycie jednej nazwy (np. print, add, compare).
  • Gdy tworzymy biblioteki i chcemy wygodnego interfejsu dla użytkownika.

11. Podsumowanie

Funkcje przeciążone to jeden z mechanizmów polimorfizmu w C++. Umożliwiają:

  • większą czytelność,
  • elastyczność,
  • spójne nazwy funkcji,
  • wygodniejsze korzystanie z kodu.

Trzeba jednak uważać na:

  • niejednoznaczność,
  • konwersje typów,
  • parametry domyślne,
  • przeciążanie niepoparte logiką.