Funktionsöverbelastning

I vissa programmeringsspråk är funktionsöverbelastning eller metodöverbelastning möjligheten att skapa flera funktioner med samma namn med olika implementeringar . Anrop till en överbelastad funktion kommer att köra en specifik implementering av den funktionen som passar anropets sammanhang, vilket gör att ett funktionsanrop kan utföra olika uppgifter beroende på sammanhang.

Till exempel är doTask() och doTask(objekt o) överbelastade funktioner. För att anropa den senare måste ett objekt skickas som en parameter , medan det förra inte kräver en parameter och anropas med ett tomt parameterfält. Ett vanligt fel skulle vara att tilldela ett standardvärde till objektet i den andra funktionen, vilket skulle resultera i ett tvetydigt anropsfel , eftersom kompilatorn inte skulle veta vilken av de två metoderna som ska användas.

Ett annat exempel är en Print(object o) -funktion som utför olika åtgärder baserat på om det är att skriva ut text eller foton. De två olika funktionerna kan vara överbelastade som Print(text_object T); Skriv ut (bildobjekt P) . Om vi ​​skriver de överbelastade utskriftsfunktionerna för alla objekt kommer vårt program att "skriva ut", vi behöver aldrig oroa oss för typen av objekt, och rätt funktionsanrop igen, anropet är alltid: Print(något ) .

Språk som stöder överbelastning

Språk som stöder funktionsöverbelastning inkluderar, men är inte nödvändigtvis begränsade till, följande:

Regler vid funktionsöverbelastning

  • Samma funktionsnamn används för mer än en funktionsdefinition
  • Funktionerna måste skilja sig åt antingen genom arten eller typen av deras parametrar

Det är en klassificering av statisk polymorfism där ett funktionsanrop löses med hjälp av någon "bästa matchning"-algoritm, där den specifika funktionen att anropa löses genom att hitta den bästa matchningen av de formella parametertyperna med de faktiska parametertyperna. Detaljerna i denna algoritm varierar från språk till språk.

Funktionsöverbelastning associeras vanligtvis med statiskt skrivna programmeringsspråk som tvingar fram typkontroll i funktionsanrop . En överbelastad funktion är egentligen bara en uppsättning olika funktioner som råkar ha samma namn. Bestämningen av vilken funktion som ska användas för ett visst samtal löses vid kompileringstillfället .

I Java är funktionsöverbelastning också känd som kompileringstidspolymorfism och statisk polymorfism.

Funktionsöverbelastning ska inte förväxlas med former av polymorfism där valet görs vid körning, t.ex. genom virtuella funktioner istället för statiskt.

Exempel: Funktionsöverbelastning i C++

 

     
       


       
         


         
       


  
    
     
      
 #include  <iostream>  int  Volym  (  int  s  )  {  // Volym av en kub.  returnera  s  *  s  *  s  ;  }  dubbel  Volym  (  dubbel  r  ,  int  h  )  {  // Volym av en cylinder.  return  3,1415926  *  r  *  r  *  static_cast  <  double  >  (  h  );  }  long  Volym  (  long  l  ,  int  b  ,  int  h  )  {  // Volym av en kuboid.  returnera  l  *  b  *  h  ;  }  int  main  ()  {  std  ::  cout  <<  Volym  (  10  );  std  ::  cout  <<  Volym  (  2,5  ,  8  );  std  ::  cout  <<  Volym  (  100l  ,  75  ,  15  );  } 

I exemplet ovan beräknas volymen för varje komponent med en av de tre funktionerna som kallas "volym", med val baserat på olika antal och typ av faktiska parametrar.

Konstruktör överbelastning

Konstruktörer , som används för att skapa instanser av ett objekt, kan också vara överbelastade i vissa objektorienterade programmeringsspråk . Eftersom konstruktörens namn på många språk är förutbestämt av klassens namn, verkar det som att det bara kan finnas en konstruktor. Närhelst flera konstruktörer behövs ska de implementeras som överbelastade funktioner. I C++ tar standardkonstruktörer inga parametrar, vilket instansierar objektmedlemmarna med deras lämpliga standardvärden, "som normalt är noll för numeriska fält och tom sträng för strängfält" . Till exempel kan en standardkonstruktor för ett restaurangfakturaobjekt skrivet i C++ ställa in tipset till 15 %:


      
      
  Bill  ()  :  tips  (  0,15  ),  // procentsats  totalt  (  0,0  )  {  } 

Nackdelen med detta är att det krävs två steg för att ändra värdet på det skapade Bill-objektet. Följande visar skapande och ändring av värden i huvudprogrammet:

 
  
   Bill  café  ;  kafé  .  spets  =  0,10  ;  kafé  .  totalt  =  4,00  ; 

Genom att överbelasta konstruktorn kunde man skicka spetsen och summan som parametrar vid skapandet. Detta visar den överbelastade konstruktorn med två parametrar. Denna överbelastade konstruktor placeras i klassen såväl som den ursprungliga konstruktorn vi använde tidigare. Vilken som används beror på antalet parametrar som tillhandahålls när det nya Bill-objektet skapas (ingen eller två):

   
     
      
  Bill  (  dubbelt  dricks  ,  dubbelt  totalt  )  :  dricks  (  dricks  ),  totalt  (  totalt  )  {  } 

Nu kan en funktion som skapar ett nytt Bill-objekt skicka två värden till konstruktorn och ställa in datamedlemmarna i ett steg. Följande visar skapande och inställning av värden:

   Bill  café  (  0,10  ,  4,00  ); 

Detta kan vara användbart för att öka programmets effektivitet och minska kodlängden.

En annan anledning till överbelastning av konstruktörer kan vara att tvinga fram obligatoriska datamedlemmar. I det här fallet förklaras standardkonstruktorn privat eller skyddad (eller helst raderad sedan C++11 ) för att göra den oåtkomlig utifrån. För räkningen ovan kan total vara den enda konstruktorparametern – eftersom en räkning inte har någon vettig standard för total – medan tip har som standard 0,15.

Komplikationer

Två problem interagerar med och komplicerar funktionsöverbelastning: Namnmaskering (på grund av scope ) och implicit typkonvertering .

Om en funktion deklareras i ett scope, och sedan en annan funktion med samma namn deklareras i ett inre scope, finns det två naturliga möjliga överbelastningsbeteenden: den inre deklarationen maskerar den yttre deklarationen (oavsett underskrift), eller båda den inre deklarationen och den yttre deklarationen ingår båda i överbelastningen, med den inre deklarationen maskerar den yttre deklarationen endast om signaturen stämmer överens. Den första är tagen i C++: "i C++ finns ingen överbelastning över scopes." Som ett resultat, för att få en överbelastningsuppsättning med funktioner deklarerade i olika omfång, måste man explicit importera funktionerna från det yttre omfånget till det inre omfånget, med det använda nyckelordet.

Implicit typkonvertering komplicerar funktionsöverbelastning eftersom om typerna av parametrar inte exakt matchar signaturen för en av de överbelastade funktionerna, men kan matcha efter typkonvertering, beror upplösningen på vilken typkonvertering som väljs.

Dessa kan kombineras på förvirrande sätt: En inexakt matchning som deklareras i ett inre omfång kan maskera en exakt matchning som deklareras i ett yttre omfång, till exempel.

Till exempel, för att ha en härledd klass med en överbelastad funktion som tar en dubbel eller en int , med funktionen som tar en int från basklassen, i C++, skulle man skriva:

  
 
    


     
 
   
    
 klass  B  {  public  :  void  F  (  int  i  );  };  class  D  :  public  B  {  public  :  using  B  ::  F  ;  tomrum  F  (  dubbel  d  );  }; 

Att misslyckas med att inkludera användningen resulterar i att en int- parameter som skickas till F i den härledda klassen konverteras till en dubbel och matchar funktionen i den härledda klassen, snarare än i basklassen; Inklusive att använda resulterar i en överbelastning i den härledda klassen och därmed matcha funktionen i basklassen.

Varningar

Om en metod är designad med ett för stort antal överbelastningar kan det vara svårt för utvecklare att urskilja vilken överbelastning som anropas genom att bara läsa koden. Detta gäller särskilt om några av de överbelastade parametrarna är av typer som är ärvda typer av andra möjliga parametrar (till exempel "objekt"). En IDE kan utföra överbelastningsupplösningen och visa (eller navigera till) rätt överbelastning.

Typbaserad överbelastning kan också försvåra kodunderhåll, där koduppdateringar av misstag kan ändra vilken metod överbelastning som väljs av kompilatorn.

Se även

externa länkar