Przeciążanie funkcji

Z Wikipedii, wolnej encyklopedii

Przeciążanie funkcji (ang. overloading) – skrótowa nazwa na przeciążanie nazwy funkcji; w programowaniu występowanie pod taką samą nazwą wielu funkcji różniących się zestawem argumentów. W trakcie kompilacji bądź parsowania program znajduje właściwą funkcję po liczbie oraz typach argumentów. Możliwe jest więc współistnienie kilku funkcji o tej samej nazwie, lecz różniących się typami argumentów.

Przykłady[edytuj | edytuj kod]

Przykład w języku C++[edytuj | edytuj kod]

void funkcja (int);

void funkcja (int, char);

void funkcja (float, int);

Przykład w języku Object Pascal[edytuj | edytuj kod]

Przeciążanie funkcji w języku Object Pascal dostępne jest od środowiska Delphi w wersji 4. Możliwe jest zarówno przeciążanie funkcji jak i procedur. Przeciążenie możliwe jest dzięki dodaniu klauzuli overload po nazwie i parametrach funkcji.

procedure Foo(f: integer); overload;

procedure Foo(s: string; f: integer); overload;

procedure Foo(d: double; f: integer); overload;

Przykład w języku PL/1[edytuj | edytuj kod]

Nieco inaczej przeciążanie nazw realizowano w historycznych już dzisiaj językach. Jako przykład posłużyć może deklaracja rodziny procedur w języku PL/1, w którym definiowano różne procedury, a następnie nazwę nowej procedury i listę procedur wywoływanych przez tę nazwę dla konkretnych przypadków listy argumentów[1]. Przykład w PL/1:

DCL A GENERIC (PR1 WHEN(FLOAT),
               PR2 WHEN(CHAR),
               PR3 WHEN(FLOAT, CHAR),
               PR4 WHEN(LABEL));

Przykład w języku Forth[edytuj | edytuj kod]

Jeszcze inaczej przeciążanie funkcji (lub ogólniej identyfikatorów) traktowane jest w języku Forth, co wynika ze specyfiki tego języka. W języku Forth definiujemy słowa (które mogą oznaczać podprogram, stałą, zmienną, słownik, kompilator (w sensie języka Forth)). Język umożliwia definiowanie słów w określonych słownikach. Dzięki temu można przeciążać nazwy lecz nie w obrębie pojedynczego słownika, ale w obrębie całej (drzewiastej) struktury słowników, umieszczając słowa o tych samych nazwach w różnych słownikach. Zmieniając kolejność przeszukiwania słowników, wybierane będą różne podprogramy (z różnych słowników o tej samej nazwie)[2][3].

Przykład:

VOC1 DEFINITIONS
: OP-D DUP ROT DUP + ;
VOC2 DEFINITIONS
: OP-D DUP ROT DUP * ;
VOC3 DEFINITIONS
: OP-D DUP ROT DUP - ;
VOC4 DEFINITIONS
: OP-D DUP ROT DUP / ;

...

3 4
VOC1
OP-D .
VOC2
OP-D .

Powyższy przykład definiuje podprogram OP-D, który w zależności od tego, który ze słowników VOC1, VOC2, VOC3, VOC4 będzie przeszukiwany w pierwszej kolejności wykona dodawanie, mnożenie, odejmowanie lub dzielenie, z zachowaniem argumentów operacji. Działanie powyższych instrukcji spowoduje wyprowadzenie liczby 7 (3+4), a następnie 12 (3*4).

Sytuacje niejednoznaczne i błędy przeciążania[edytuj | edytuj kod]

Nie zawsze kompilator jest w stanie odpowiednio odróżnić funkcje o tej samej nazwie, muszą się one od siebie wyraźnie różnić. Czasem zdarzają się też sytuacje, w której dwie funkcje o tej samej nazwie mogą współistnieć, ale dane wywołanie byłoby niejednoznaczne. Problemy są następujące:

  • Jeśli funkcje (jedna lub obie) przyjmują argumenty domyślne, to mogą współistnieć jeśli te „niedomyślne” argumenty mają te same typy, tyle że wywołanie z podaniem wyłącznie wymaganych argumentów będzie wtedy niejednoznaczne (i odrzucone). Najlepiej nie mieszać ze sobą przeciążania i argumentów domyślnych.
  • Podczas wybierania funkcji do wywołania uwzględnia się też domyślne konwersje i trzeba znać ich priorytety; np. jeśli funkcję przeciążymy na typy short i long, to wywołanie z typem float jest niejednoznaczne.
  • W zależności od języka przeciążać można tylko na podstawie typów parametrów, lub na podstawie typów parametrów i wartości zwracanej (np. w języku Ada).
  • Uzyskanie wskaźnika do przeciążonej funkcji jest niemożliwe. Udaje się to tylko w przypadku wyrażeń, w których oczekuje się konkretnego typu od takiego wyrażenia, np. przypisując do zmiennej typu wskaźnika do funkcji – wtedy zostanie wybrana ta funkcja, która pasuje do sygnatury funkcji, do której jest ten wskaźnik. Nie można jednak takiej funkcji używać jako argumentu do szablonu funkcji – jest to znany problem z używaniem funkcji std::transform wraz ze std::tolower.

Zobacz też[edytuj | edytuj kod]

Przypisy[edytuj | edytuj kod]

  1. Jan Bielecki: Rozszerzony PL/I i JCL w systemie OS/RIAD. Warszawa: Państwowe Wydawnictwo Naukowe, 1986, seria: Biblioteka Informatyki. ISBN 83-01-06146-4. (pol.).
  2. Jan Bielecki: Język FORTH. Warszawa: Wydawnictwa Naukowo-Techniczne, 1988, seria: Mikrokomputery. ISBN 83-204-0930-6. (pol.).
  3. Jan Ruszczyc: Poznajemy FORTH. Warszawa: SOETO, 1987, seria: Informatyka mikrokomputerowa. (pol.).