Rozważ następującą funkcję:
int add(int x, int y)
{
return x + y;
}Ta trywialna funkcja dodaje dwie liczby całkowite i zwraca wynik w postaci całkowitej. Co jednak, jeśli potrzebujemy także funkcji, która może dodawać dwie liczby zmiennoprzecinkowe? Ta add() funkcja nie jest odpowiednia, ponieważ wszelkie parametry zmiennoprzecinkowe zostałyby zamienione na liczby całkowite, co spowodowałoby utratę wartości ułamkowych argumentów zmiennoprzecinkowych.
Jednym ze sposobów obejścia tego problemu jest zdefiniowanie wielu funkcji o nieco innych nazwach:
int addInteger(int x, int y)
{
return x + y;
}
double addDouble(double x, double y)
{
return x + y;
}Jednak aby uzyskać najlepszy efekt, wymaga to zdefiniowania spójnego standardu nazewnictwa funkcji dla podobnych funkcji, które mają parametry różnych typów, zapamiętania nazw tych funkcji i faktycznego wywołania poprawnych jeden.
A co się stanie, gdy będziemy chcieli mieć podobną funkcję, która dodaje 3 liczby całkowite zamiast 2? Zarządzanie unikalnymi nazwami każdej funkcji szybko staje się uciążliwe.
Wprowadzenie do przeciążania funkcji
Na szczęście C++ ma eleganckie rozwiązanie do obsługi takich przypadków. Przeciążanie funkcji pozwala nam tworzyć wiele funkcji o tej samej nazwie, pod warunkiem, że każda funkcja o identycznej nazwie ma inny typ parametrów (lub funkcje można w inny sposób różnicować). Każda funkcja o wspólnej nazwie (w tym samym zakresie) nazywana jest funkcją przeciążoną (czasami nazywany przeciążeniem w skrócie).
Aby przeciążyć naszą add() funkcję, możemy po prostu zadeklarować inną add() funkcję, która przyjmuje podwójne parametry:
double add(double x, double y)
{
return x + y;
}Mamy teraz dwie wersje add() w tym samym zakresie:
int add(int x, int y) // integer version
{
return x + y;
}
double add(double x, double y) // floating point version
{
return x + y;
}
int main()
{
return 0;
}Powyższy program zostanie skompilowany. Chociaż można się spodziewać, że te funkcje spowodują konflikt nazewnictwa, w tym przypadku tak nie jest. Ponieważ typy parametrów tych funkcji różnią się, kompilator jest w stanie rozróżnić te funkcje i potraktuje je jako osobne funkcje, które tak się składa, że mają wspólną nazwę.
Kluczowa informacja
Funkcje mogą być przeciążane, o ile każda przeciążona funkcja może zostać rozróżniona przez kompilator. Jeśli przeciążona funkcja nie może zostać zróżnicowana, wystąpi błąd kompilacji.
Powiązana treść
Operatory można również przeciążać w podobny sposób. Przeciążanie operatorów omówimy w 21.1 — Wprowadzenie do przeciążania operatorów.
Wprowadzenie do rozwiązywania przeciążeń
Dodatkowo, gdy wykonywane jest wywołanie funkcji do funkcji, która została przeciążona, kompilator spróbuje dopasować wywołanie funkcji do odpowiedniego przeciążenia w oparciu o argumenty użyte w wywołaniu funkcji. Nazywa się to rozwiązywaniem przeciążenia.
Oto prosty przykład ilustrujący to:
#include <iostream>
int add(int x, int y)
{
return x + y;
}
double add(double x, double y)
{
return x + y;
}
int main()
{
std::cout << add(1, 2); // calls add(int, int)
std::cout << '\n';
std::cout << add(1.2, 3.4); // calls add(double, double)
return 0;
}Powyższy program kompiluje i generuje wynik:
3 4.6
Gdy w wywołaniu add(1, 2) podamy argumenty zmiennoprzecinkowe, kompilator ustali, że próbujemy wywołać add(int, int). A kiedy w wywołaniu add(1.2, 3.4) podamy argumenty zmiennoprzecinkowe, kompilator ustali, że próbujemy wywołać add(double, double).
Sprawienie, aby się skompilował
Aby program korzystający z przeciążonych funkcji mógł się skompilować, muszą być spełnione dwie rzeczy:
- Każda przeciążona funkcja musi być odróżniona od pozostałych. W lekcji 11.2 -- Różnicowanie przeciążenia funkcji.
- każde wywołanie przeciążonej funkcji musi dać odpowiedź na przeciążoną funkcję. W lekcji 11.3 — Rozwiązywanie przeciążenia funkcji i dopasowania niejednoznaczne.
jak kompilator dopasowuje wywołania funkcji do przeciążonych funkcji, omawiamy w lekcji<<<M30>>>Jeśli przeciążona funkcja nie jest zróżnicowana lub jeśli wywołanie funkcji przeciążonej nie może zostać przekształcone w przeciążoną funkcję, wówczas wystąpi błąd kompilacji.
W następnej lekcji przyjrzymy się, jak można rozróżnić przeciążone funkcje. Następnie w następnej lekcji przyjrzymy się, jak kompilator rozwiązuje wywołania funkcji do przeciążonych funkcji.
Wnioski
Przeciążanie funkcji to świetny sposób na zmniejszenie złożoności programu poprzez zmniejszenie liczby nazw funkcji, które należy zapamiętać. Można i należy z niego korzystać swobodnie.
Najlepsza praktyka
Użyj przeciążania funkcji, aby uprościć swój program.

