Cerca nel sito:
ricerca
avanzata

Frasi Celebri...

Non importa chi fosse mio padre; importa ci? che mi ricordo che fosse.

Anne Sexton 

Sondaggio:

Quale auto per non passare inosservati?

Jaguar
Mercedes
Ferrari
Maserati
Bmw
AlfaRomeo
Bugatti

visualizza risultati


 

Overloading delle funzioni

Il termine overloading (da to overload) significa sovraccaricamento e nel contesto del C++ overloading delle funzioni indica la possibilita` di attribuire allo stesso nome di funzione piu` significati. Attribuire piu` significati vuol dire fare in modo che lo stesso nome di funzione sia in effetti utilizzato per piu` funzioni contemporaneamente.
Un esempio di overloading ci viene dalla matematica, dove con spesso utilizziamo lo stesso nome di funzione con significati diversi senza starci a pensare troppo, ad esempio + e` usato sia per indicare la somma sui naturali che quella sui reali...
Ritorniamo per un attimo alla nostra funzione Sum...
Per come e` stata definita, Sum funziona solo sugli interi e non e` possibile utilizzarla sui float. Quello che vogliamo e` riutilizzare lo stesso nome, attribuendogli un significato diverso e lasciando al compilatore il compito di capire quale versione della funzione va utilizzata di volta in volta. Per fare cio` basta definire piu` volte la stessa funzione:

 

int Sum(int a, int b);       // per sommare due interi,
float Sum(float a, float b); // per sommare due float,

float Sum(float a, int b);   // per la somma di un
float Sum(int a, float b);   // float e un intero.

 

Nel nostro esempio ci siamo limitati solo a dichiarare piu` volte la funzione Sum, ogni volta con un significato diverso (uno per ogni possibile caso di somma in cui possono essere coinvolti, anche contemporaneamente, interi e reali); e` chiaro che poi da qualche parte deve esserci una definizione per ciascun prototipo (nel nostro caso tutte le definizioni sono identiche a quella gia` vista, cambia solo l'intestazione della funzione).
In alcune vecchie versioni del C++ l'intenzione di sovraccaricare una funzione doveva essere esplicitamente comunicata al compilatore tramite la keyword overload:

 

overload Sum; // ora si puo`
              // sovraccaricare Sum:

int Sum(int a, int b);
float Sum(float a, float b);
float Sum(float a, int b);
float Sum(int a, float b);

 

Comunque si tratta di una pratica obsoleta che infatti non e` prevista nello standard.
Le funzioni sovraccaricate si utilizzano esattamente come le normali funzioni:

 

#include < iostream >
using namespace std;

/* Dichiarazione ed implementazione delle varie Sum */

int main(int, char* []) {
  int a = 5;
  int y = 10;
  float f = 9.5;
  float r = 0.5;

  cout << "Sum(int, int):" << endl;
  cout << " " << Sum(a, y) << endl;

  cout << "Sum(float, float):" << endl;
  cout << " " << Sum(f, r) << endl;

  cout << "Sum(int, float):" << endl;
  cout << " " << Sum(a, f) << endl;

  cout << "Sum(float, int):" << endl;
  cout << " " << Sum(r, a) << endl;

  return 0;
}

 

E` il compilatore che decide quale versione di Sum utilizzare, in base ai parametri forniti; infatti e` possibile eseguire l'overloading di una funzione solo a condizione che la nuova versione differisca dalle precedenti almeno nei tipi dei parametri (o che questi siano forniti in un ordine diverso, come mostrano le ultime due definizioni di Sum viste sopra):

 

void Foo(int a, float f);
int Foo(int a, float f);   // Errore!
int Foo(float f, int a);   // Ok!
char Foo();                // Ok!
char Foo(...);             // OK!

 

La seconda dichiarazione e` errata perche`, per scegliere tra la prima e la seconda versione della funzione, il compilatore si basa unicamente sui tipi dei parametri che nel nostro caso coincidono; la soluzione e` mostrata con la terza dichiarazione, ora il compilatore e` in grado di distinguere perche` il primo parametro anzicche` essere un int e` un float. Infine le ultime due dichiarazioni non sono in conflitto per via delle regole che il compilatore segue per scegliere quale funzione applicare; in linea di massima e secondo la loro priorita`:

  1. Match esatto: se esiste una versione della funzione che richiede esattamente quel tipo di parametri (i parametri vengono considerati a uno a uno secondo l'ordine in cui compaiono) o al piu` conversioni banali (tranne da T* a const T* o a volatile T*, oppure da T& a const T& o a volatile T&);
  2. Mach con promozione: si utilizza (se esiste) una versione della funzione che richieda al piu` promozioni di tipo (ad esempio da int a long int, oppure da float a double);
  3. Mach con conversioni standard: si utilizza (se esiste) una versione della funzione che richieda al piu` conversioni di tipo standard (ad esempio da int a unsigned int);
  4. Match con conversioni definite dall'utente: si tenta un matching con una definizione (se esiste), cercando di utilizzare conversioni di tipo definite dal programmatore;
  5. Match con ellissi: si esegue un matching utilizzando (se esiste) una versione della funzione che accetti un qualsiasi numero e tipo di parametri (cioe` funzioni nel cui prototipo e` stato utilizzato il simbolo ...);

Se nessuna di queste regole puo` essere applicata, si genera un errore (funzione non definita!). La piena comprensione di queste regole richiede la conoscenza del concetto di conversione di tipo per il quale si rimanda all'appendice A; si accenna inoltre ai tipi puntatore e reference che saranno trattati nel prossimo capitolo, infine si fa riferimento alla keyword volatile. Tale keyword serve ad informare il compilatore che una certa variabile cambia valore in modo aleatorio e che di conseguenza il suo valore va riletto ogni volta che esso sia richiesto:

 

volatile int ComPort;

 

La precedente definizione dice al compilatore che il valore di ComPort e` fuori dal controllo del programma (ad esempio perche` la variabile e` associata ad un qualche registro di un dispositivo di I/O).
Il concetto di overloading di funzioni si estende anche agli operatori del linguaggio, ma questo e` un argomento che riprenderemo piu` avanti.

 

successivo
–«  INDICE  »–

 

 

 

 
Powered by paper&pencil (carta&matita ) - Copyright © 2001-2019 Cataldo Sasso