Funktionsoverbelastning - Function overloading

I nogle programmeringssprog er funktionsoverbelastning eller metodeoverbelastning muligheden for at oprette flere funktioner med samme navn med forskellige implementeringer. Opkald til en overbelastet funktion kører en specifik implementering af denne funktion, der er passende for konteksten i opkaldet, så et funktionsopkald kan udføre forskellige opgaver afhængigt af kontekst.

For eksempel doTask()og doTask(object o)er overbelastede funktioner. For at kalde sidstnævnte skal et objekt sendes som en parameter , hvorimod førstnævnte ikke kræver en parameter og kaldes med et tomt parameterfelt. En almindelig fejl ville være at tildele en standardværdi til objektet i den anden funktion, hvilket ville resultere i en tvetydig opkaldsfejl , da kompilatoren ikke ville vide, hvilken af ​​de to metoder der skal bruges.

Et andet eksempel er en Print(object o)funktion, der udfører forskellige handlinger baseret på, om det udskriver tekst eller fotos. De to forskellige funktioner kan være overbelastede som Print(text_object T); Print(image_object P). Hvis vi skriver de overbelastede print funktioner til alle objekter vores program vil "print", vi aldrig behøver at bekymre sig om, hvilken type af objektet, og den korrekte funktion opkald igen, opkaldet er altid: Print(something).

Sprog, der understøtter overbelastning

Sprog, der understøtter funktionsoverbelastning, omfatter, men er ikke nødvendigvis begrænset til, følgende:

Regler for overbelastning af funktioner

  • Det samme funktionsnavn bruges til mere end én funktionsdefinition
  • Funktionerne skal være forskellige enten efter arity eller typer af deres parametre

Det er en klassificering af statisk polymorfisme, hvor et funktionsopkald løses ved hjælp af en "bedst matchende" algoritme, hvor den særlige funktion, der skal kaldes, løses ved at finde det bedste match mellem de formelle parametertyper med de faktiske parametertyper. Detaljerne i denne algoritme varierer fra sprog til sprog.

Funktionsoverbelastning er normalt forbundet med statisk typede programmeringssprog, der håndhæver typekontrol i funktionsopkald . En overbelastet funktion er egentlig bare et sæt forskellige funktioner, der tilfældigvis har samme navn. Bestemmelsen af, hvilken funktion der skal bruges til et bestemt opkald, løses på kompileringstidspunktet .

I Java er funktionsoverbelastning også kendt som kompileringstidspolymorfisme og statisk polymorfisme.

Funktionsoverbelastning bør ikke forveksles med former for polymorfisme, hvor valget træffes ved runtime, f.eks. Gennem virtuelle funktioner , i stedet for statisk.

Eksempel: Funktionsoverbelastning i C ++

#include <iostream>

int Volume(int s) {  // Volume of a cube.
  return s * s * s;
}

double Volume(double r, int h) {  // Volume of a cylinder.
  return 3.1415926 * r * r * static_cast<double>(h);
}

long Volume(long l, int b, int h) {  // Volume of a cuboid.
  return l * b * h;
}

int main() {
  std::cout << Volume(10);
  std::cout << Volume(2.5, 8);
  std::cout << Volume(100l, 75, 15);
}

I ovenstående eksempel beregnes volumenet for hver komponent ved hjælp af en af ​​de tre funktioner med navnet "volumen", med valg baseret på det forskellige antal og typen af ​​faktiske parametre.

Konstruktør overbelastning

Konstruktører , der bruges til at oprette forekomster af et objekt, kan også være overbelastet i nogle objektorienterede programmeringssprog . Fordi konstruktørens navn på mange sprog er forudbestemt af klassens navn, ser det ud til, at der kun kan være en konstruktør. Når der er brug for flere konstruktører, skal de implementeres som overbelastede funktioner. I C ++ , standardindstillinger konstruktører tager nogen parametre, instantiere objektet medlemmer med deres relevante standardværdier. For eksempel kan en standardkonstruktør for et restaurantregningsobjekt skrevet i C ++ sætte spidsen til 15%:

Bill()
    : tip(0.15), // percentage
      total(0.0)
{ }

Ulempen ved dette er, at det tager to trin at ændre værdien af ​​det oprettede Bill -objekt. Følgende viser oprettelse og ændring af værdierne i hovedprogrammet:

Bill cafe;
cafe.tip = 0.10;
cafe.total = 4.00;

Ved at overbelaste konstruktøren kunne man passere spidsen og total som parametre ved oprettelsen. Dette viser den overbelastede konstruktør med to parametre. Denne overbelastede konstruktør er placeret i klassen såvel som den originale konstruktør, vi brugte før. Hvilken der bruges, afhænger af antallet af parametre, der tilvejebringes, når det nye Bill -objekt oprettes (ingen eller to):

Bill(double tip, double total)
    : tip(tip),
      total(total)
{ }

Nu kan en funktion, der opretter et nyt Bill -objekt, sende to værdier ind i konstruktøren og indstille datamedlemmerne i et trin. Følgende viser oprettelse og indstilling af værdierne:

Bill cafe(0.10, 4.00);

Dette kan være nyttigt til at øge programmets effektivitet og reducere kodelængden.

En anden grund til konstruktoroverbelastning kan være at håndhæve obligatoriske datamedlemmer. I dette tilfælde erklæres standardkonstruktøren for privat eller beskyttet (eller helst slettet siden C ++ 11 ) for at gøre det utilgængeligt udefra. For regningen kan overordnet total være den eneste konstruktørparameter - da en regning ikke har nogen fornuftig standard for total - hvorimod tip er standard til 0,15.

Komplikationer

To spørgsmål interagerer med og komplicerer funktionsoverbelastning: Navnemaske (på grund af omfang ) og implicit typekonvertering .

Hvis en funktion er erklæret i et omfang, og derefter en anden funktion med samme navn er erklæret i et indre omfang, er der to naturlige mulige overbelastningsadfærd: den indre erklæring maskerer den ydre erklæring (uanset signatur) eller begge den indre erklæring og den ydre erklæring er begge inkluderet i overbelastningen, idet den indre erklæring kun dækker den ydre erklæring, hvis signaturen stemmer overens. Den første er taget i C ++: "i C ++ er der ingen overbelastning på tværs af omfang." Som et resultat heraf skal man eksplicit importere funktionerne fra det ydre omfang til det indre omfang med usingsøgeordet for at opnå et overbelastningssæt med funktioner, der er deklareret i forskellige omfang .

Implicit typekonvertering komplicerer funktionsoverbelastning, fordi hvis parametertyperne ikke nøjagtigt matcher signaturen for en af ​​de overbelastede funktioner, men kan matche efter konvertering af typen, afhænger opløsningen af, hvilken type konvertering der vælges.

Disse kan kombineres på forvirrende måder: En unøjagtig match erklæret i et indre omfang kan for eksempel maskere en nøjagtig match, der er erklæret i et ydre omfang.

For eksempel, for at have en afledt klasse med en overbelastet funktion, der tager en doubleeller en int, ved hjælp af funktionen, der tager en intfra basisklassen, i C ++, ville man skrive:

class B {
 public:
  void F(int i);
};

class D : public B {
 public:
  using B::F;
  void F(double d);
};

Ikke at inkludere usingresultaterne i en intparameter, der blev videregivet til Fi den afledte klasse, konverteres til en dobbelt og matcher funktionen i den afledte klasse, snarere end i baseklassen; Inkluderer usingresultater i en overbelastning i den afledte klasse og dermed matchning af funktionen i grundklassen.

Advarsler

Hvis en metode er designet med et for stort antal overbelastninger, kan det være svært for udviklere at se, hvilken overbelastning der kaldes ved blot at læse koden. Dette er især sandt, hvis nogle af de overbelastede parametre er af typer, der er arvet typer af andre mulige parametre (f.eks. "Objekt"). En IDE kan udføre overbelastningsopløsningen og vise (eller navigere til) den korrekte overbelastning.

Typebaseret overbelastning kan også hæmme kodevedligeholdelse, hvor kodeopdateringer ved et uheld kan ændre hvilken metodeoverbelastning, der vælges af kompilatoren.

Se også

Referencer

eksterne links