Historia pytania
C++ od samego początku był projektowany jako język wspierający przeciążenie funkcji — możliwość zadeklarowania kilku funkcji o tej samej nazwie, ale różnych parametrach. Pozwala to na tworzenie czytelnego i wygodnego API.
Problem
Gdy pojawia się wiele funkcji o tej samej nazwie, kompilator musi wybrać odpowiednią implementację spośród wszystkich przeciążonych, uwzględniając typy argumentów, konwersje, parametry domyślne i referencje. Przy nieuważnym przeciążeniu mogą pojawić się niejednoznaczności i trudno wykrywalne błędy.
Rozwiązanie
Kompilator wybiera funkcję na podstawie najlepszego dopasowania sekwencji argumentów, dokładności dopasowania typu i minimalnych przekształceń. Należy jednak pamiętać o niuansach: jeśli występują znaczące konwersje lub argumenty domyślne, można nieoczekiwanie napotkać niejednoznaczność.
Przykład kodu:
void foo(int x); void foo(double x); void foo(int x, int y = 0); foo(5); // wywoła void foo(int x), ponieważ to jest dokładne trafienie foo(5.2); // wywoła void foo(double x) foo(5, 6); // wywoła void foo(int x, int y)
Kluczowe cechy:
Czy można przeciążyć funkcje tylko na podstawie typu zwracanego?
Nie. Przeciążenie jest możliwe TYLKO na podstawie typu i liczby parametrów, typ zwracany nie bierze udziału w rozwiązywaniu przeciążenia.
int foo(); double foo(); // Błąd: przeciążenie tylko na podstawie typu zwracanego jest niemożliwe!
Jak kompilator wybiera, którą przeciążoną funkcję wywołać, jeśli wszystkie parametry są konwertowalne?
Kompilator wybiera "najlepsze dopasowanie" — funkcję, dla której wymagana jest minimalna liczba konwersji typów lub dokładne dopasowanie. Jeśli występuje niejednoznaczność, kod nie zostanie skompilowany.
void bar(int); void bar(long); bar(1); // int dokładne trafienie: wywoła się bar(int)
Czy można mieszać przeciążenie w oparciu o argumenty domyślne i zwykłe przeciążenie?
Można, ale można napotkać niejednoznaczność wywołania, jeśli sygnatury funkcji się pokrywają.
void test(int x); void test(int x, int y = 10); test(5); // Błąd: niejednoznaczność — obie pasują
W bibliotece występują przeciążone funkcje z pokrywającymi się argumentami domyślnymi, co prowadzi do błędów kompilacji podczas aktualizacji kodu.
Zalety:
Wady:
W projekcie wprowadzono umowę — nie mieszać przeciżeń z argumentami domyślnymi, albo używać tylko jednej funkcji z domyślnymi wartościami, albo czysto przeciążać na podstawie unikalnych parametrów.
Zalety:
Wady: