Lezione 7 Sovrapposizione di Funzioni Sovrapposizione di Funzioni Lezione 7 ü La sovrapposizione (overloading) è un meccanismo che consente di assegnare ad un nome significati differenti ® ü La Quando il nome viene utilizzato in una frase il significato corretto viene specificato dal contesto sovrapposizione linguaggi naturali ® è utilizzata ampiamente nei Es. conti (titolo nobiliare e sequenza di calcoli aritmetici) ü Per evitare situazioni di ambiguità il contesto della frase deve chiarire il corretto significato da dare al nome Laboratorio di Algoritmi e Strutture Dati 2001 -02 Sovrapposizione di un Nome 1 Laboratorio di Algoritmi e Strutture Dati 2001/02 1 Lezione 7 Sovrapposizione di Funzioni ü Il C++ contiene diversi esempi di “parole” che hanno significati sovrapposti ® ® gli operatori +, -, *, / etc. etc. (dipende dagli operandi) i nomi delle variabili (dipendono dal campo di visibilità) ü Il contesto dell’espressione in cui compare l'identificatore chiarisce il suo significato ® altrimenti il compilatore segnala un errore di ambiguità Laboratorio di Algoritmi e Strutture Dati 2001 -02 Sovrapposizione di Identificatori 2 ü Il C++ consente di sovrapporre il nome di una funzione ® il programma contiene più funzioni che hanno lo stesso nome ma comportamenti differenti ü Le varie versioni della funzione devono avere firme differenti ® la firma di una funzione è costituita dal nome della funzione e dal tipo dei suoi parametri ü Tutte le versioni sovrapposte della funzione devono essere definite nello stesso scope ü La risoluzione dell’overloading di funzioni è uno degli aspetti più complessi del C++ Laboratorio di Algoritmi e Strutture Dati 2001 -02 Sovrapposizione di Funzioni 3 Laboratorio di Algoritmi e Strutture Dati 2001/02 2 Lezione 7 Sovrapposizione di Funzioni Perché Sovrapporre Funzioni definire un gruppo di funzioni differenti che svolgono la stessa operazione logica int max(int, int); // massimo tra due interi int max(int*, int); // massimo in un vettore di interi int max(Lista&); // massimo in una lista di interi ü La scelta della versione corretta della funzione è effettuata dal compilatore sulla base degli argomenti della chiamata a funzione Laboratorio di Algoritmi e Strutture Dati 2001 -02 ü Sovrapporre il nome di una funzione consente di 4 Perché Sovrapporre Funzioni logica implementata dalla funzione ü In C tutte le funzioni devono avere nomi distinti ® il nome della funzione non può corrispondere all’operazione logica implementata ü La sovrapposizione fornisce soltanto una semplificazione lessicale, consentendo di assegnare un unico nome ad ogni operazione logica Laboratorio di Algoritmi e Strutture Dati 2001 -02 ü In C++ il nome della funzione individua l’operazione 5 Laboratorio di Algoritmi e Strutture Dati 2001/02 3 Lezione 7 Sovrapposizione di Funzioni ü Evitare di sovrapporre quando l'identificazione di più funzioni con un unico nome fa perdere informazioni Video& muoviOrigine(); Video& muoviX(int); Video& muoviY(int); Video& muovi(int, int); ü Spesso si può evitare di ricorrere alla sovrapposizione utilizzando l’inizializzazione per default dei parametri Laboratorio di Algoritmi e Strutture Dati 2001 -02 Quando non Sovrapporre 6 Sovrapposizione di Funzioni come ® redichiarazioni se la firma ed il tipo del risultato delle due dichiarazioni coincidono extern void stampa(int* ia, int dim); void stampa(int *array, int size); ® un errore se le firme coincidono ma i tipi dei risultati sono differenti unsigned int massimo(int* ia, int dim); int massimo(int *array, int size); ® dichiarazioni sovrapposte se le due firme sono distinte int media(int* array, int size); double media(double a, double b); Laboratorio di Algoritmi e Strutture Dati 2001 -02 ü Due dichiarazioni di una funzione sono considerate 7 Laboratorio di Algoritmi e Strutture Dati 2001/02 4 Lezione 7 Sovrapposizione di Funzioni ü Due dichiarazioni della stessa funzione che differiscono solo per alcuni parametri inizializzati per default non sono funzioni sovrapposte extern void stampa(int* ia, int dim); void stampa(int *array, int size = 10); Laboratorio di Algoritmi e Strutture Dati 2001 -02 Sovrapposizione e Inizializzazione per Default 8 ü Due parametri passati per valore che differiscono per il qualificatore const sono considerati uguali void f(int); void f(const int); // ridichiarazione di f() ü Due parametri passati per riferimento che differiscono per il qualificatore const sono considerati differenti void f(int&); void f(const int&); // funzione sovrapposta Laboratorio di Algoritmi e Strutture Dati 2001 -02 Sovrapposizione e Parametri Costanti 9 Laboratorio di Algoritmi e Strutture Dati 2001/02 5 Lezione 7 Sovrapposizione di Funzioni ü Tutte le funzioni di un insieme di funzioni sovrapposte devono essere dichiarate nello stesso scope void stampa(const string&); void stampa(double); // funzione sovrapposta ü Una funzione definita in uno scope locale nasconde le funzioni definite negli scope esterni e non è visibile al di fuori del suo scope namespace ASD { void stampa(int); // nasconde le due funzioni globali void f() { stampa(“ciao”); } // ERRORE } Laboratorio di Algoritmi e Strutture Dati 2001 -02 Sovrapposizione e Scope 10 Sovrapposizione e Namespace funzioni di un namespace X visibili in un namespace Y ® ® queste funzioni si sovrappongono a quelle definite in Y si può rendere visibile solo il nome del gruppo di funzioni sovrapposte namespace Lib { int max(int, int); int max(double, double); } using Lib::max; using Lib::max(int, int); Laboratorio di Algoritmi e Strutture Dati 2001 -02 ü Le dichiarazioni using possono rendere delle // ERRORE 11 Laboratorio di Algoritmi e Strutture Dati 2001/02 6 Lezione 7 Sovrapposizione di Funzioni Sovrapposizione e Namespace di un namespace al namespace corrente ® queste funzioni si sovrappongono a quelle definite nel namespace corrente namespace Lib { int max(int, int); int max(double, double); } extern int max(int *, int); using Lib::max; void funzione() { max(23, 44); // chiama int max(int, int); } Laboratorio di Algoritmi e Strutture Dati 2001 -02 ü Le dichiarazioni using aggiungono tutti i membri 12 ü Le direttive using aggiungono tutti i membri di un namespace al campo di azione A (scope) in cui il namespace è stato definito ® queste funzioni si sovrappongono a quelle definite nel campo di azione A ü E' possibile sovrapporre anche funzioni C, definite in linkage directive ® ® la linkage directive viene applicata dopo aver risolto il nome nell'insieme delle funzioni sovrapposte ci può stare una sola funzione C Laboratorio di Algoritmi e Strutture Dati 2001/02 Laboratorio di Algoritmi e Strutture Dati 2001 -02 Sovrapposizione e Namespace 13 7 Lezione 7 Sovrapposizione di Funzioni Implementazione della Sovrapposizione meccanismo di mangling dei nomi di funzioni ü Ad ogni funzione del programma il compilatore assegna un nome interno, che dipende dalla firma della funzione ® l’algoritmo di mangling dipende dal compilatore int massimo(int, int); // in g++ diventa massimo_I_I(int, int); ü Poiché tutte le firme delle funzioni sovrapposte devono essere differenti tutte le funzioni programma hanno nomi interni distinti del Laboratorio di Algoritmi e Strutture Dati 2001 -02 ü La sovrapposizione delle funzioni è gestita attraverso il 14 ü La risoluzione di una chiamata ad una funzione sovrapposta avviene, in maniera trasparente all’utente, ® Si passa attraverso un processo di corrispondenza tra gli argomenti della chiamata ed i parametri della funzione (argument matching) ü Il compilatore confronta gli argomenti della chiamata con le firme delle varie definizioni e, se possibile, ne invoca una Laboratorio di Algoritmi e Strutture Dati 2001 -02 Risoluzione della Chiamata ad una Funzione Sovrapposta 15 Laboratorio di Algoritmi e Strutture Dati 2001/02 8 Lezione 7 Sovrapposizione di Funzioni La risoluzione avviene in tre passi 1. identificazione delle funzioni candidate funzioni che hanno lo stesso nome della funzione chiamata 2. scelta delle funzioni utilizzabili funzioni per cui gli argomenti della chiamata corrispondono ai parametri per numero e tipo 3. scelta della migliore funzione utilizzabile funzione per cui gli argomenti della chiamata corrispondono meglio ai parametri Laboratorio di Algoritmi e Strutture Dati 2001 -02 Risoluzione della Chiamata ad una Funzione Sovrapposta 16 ü Se non c'è nessuna funzione utilizzabile ® il compilatore segnala un errore di funzione non definita ü Se non c'è una migliore funzione utilizzabile ® il compilatore segnala un errore di ambiguità ü Se esiste un'unica migliore funzione utilizzabile ® il compilatore risolve la chiamata passando il controllo alla migliore funzione utilizzabile Laboratorio di Algoritmi e Strutture Dati 2001 -02 Esiti della Chiamata ad una Funzione 17 Laboratorio di Algoritmi e Strutture Dati 2001/02 9 Lezione 7 Sovrapposizione di Funzioni 1) void f(); 2) void f(int); 3) void f(double, double =3.14); 4) void f(char*, char*); f(5.6); // funzioni candidate 1, 2, 3, 4 // funzioni utilizzabili 2, 3 // miglior funzione utilizzabile 3 */ Laboratorio di Algoritmi e Strutture Dati 2001 -02 Esempio 18 ü Per individuare la migliore funzione utilizzabile il compilatore identifica il tipo di conversione che deve essere applicata ad ogni argomento per farlo corrispondere al parametro ü Per ogni argomento si può avere ® ® corrispondenza esatta (non serve conversione) corrispondenza tramite conversione w promozione w conversione standard w conversione definita dall'utente Laboratorio di Algoritmi e Strutture Dati 2001 -02 Conversioni degli Argomenti 19 Laboratorio di Algoritmi e Strutture Dati 2001/02 10 Lezione 7 Sovrapposizione di Funzioni Il tipo dell'argomento è identico al tipo del parametro int max(int, int); double max(double, double); max(10, 27); max(3.14, 6.66); Laboratorio di Algoritmi e Strutture Dati 2001 -02 Corrispondenza Esatta 20 Corrispondenza Esatta ® ® ® ® conversioni array -> puntatore conversioni funzione -> puntatore conversioni Lvalue -> Rvalue conversioni di qualificazione (solo per puntatori a costante) int a[4]; bool is_equal(const int*, const int*); void f(int *p) { if(is_equal(p, a) { …} } Laboratorio di Algoritmi e Strutture Dati 2001 -02 ü Sono corrispondenze esatte anche 21 Laboratorio di Algoritmi e Strutture Dati 2001/02 11 Lezione 7 Sovrapposizione di Funzioni ü Un Lvalue rappresenta un oggetto che può essere indirizzato ü Un Rvalue è un valore che non può essere indirizzato ® ® il valore di un'espressione una variabile temporanea ü La funzione si aspetta Rvalue come argomenti per i parametri passati per valore ® se gli argomenti sono nomi di variabili (Lvalue) devono essere convertiti a Rvalue ü La funzione si aspetta Lvalue come argomenti per i parametri passati per riferimento Laboratorio di Algoritmi e Strutture Dati 2001 -02 Conversioni Lvalue -> Rvalue 22 #include<string> string color(“rosso”); void print(string); int main() { int a,b,c; c=a+b; // L’operatore + richiede una conversione da // Lvalue in Rvalue print(color); // corrispondenza esatta: conv. da Lvalue in Rvalue return 0; } Laboratorio di Algoritmi e Strutture Dati 2001 -02 Esempio di conversioni Lvalue → Rvalue 23 Laboratorio di Algoritmi e Strutture Dati 2001/02 12 Lezione 7 Sovrapposizione di Funzioni 1) void f(const char*); 2) void f(char*); 3) void f(bool); const char* cp; f(cp); f(0); f("ciao"); f(true); f(static_cast<char *>(cp)); // corrisponde ad 1 // ambigua // corrisponde a 2 // corrisponde a 3 // corrisponde a 2 Laboratorio di Algoritmi e Strutture Dati 2001 -02 Esempi Corrispondenza Esatta 24 ü Riguarda solo i puntatori ü Si tratta di una conversione che aggiunge il qualificatore const oppure volatile al tipo puntato int *a, *b; bool is_equal(const int *, int *); int main() { if(is_equal(a, b)) cout << “true”; else cout << “false”; } // cosa stampa? // true perché effettua una conversione di qualificazione Laboratorio di Algoritmi e Strutture Dati 2001 -02 Conversione di qualificazione 25 Laboratorio di Algoritmi e Strutture Dati 2001/02 13 Lezione 7 Sovrapposizione di Funzioni ü Le conversioni ® Lvalue → Rvalue ® array → puntatore ® funzione → puntatore sono chiamate trasformazioni di Lvalue ü Una corrispondenza esatta che richiede una trasformazione di Lvalue è considerata migliore di una che richiede una conversione di qualificazione Laboratorio di Algoritmi e Strutture Dati 2001 -02 “Graduatoria” di corrispondenze esatte 26 void f(const int *); void f(int *); int main() { int p[10]; const int *cpi; f(p); // chiama void f(int *) da array a puntatore f(cpi); // chiama void f(const int *) return 0; } Laboratorio di Algoritmi e Strutture Dati 2001 -02 Esempio 27 Laboratorio di Algoritmi e Strutture Dati 2001/02 14 Lezione 7 Sovrapposizione di Funzioni ü Se il tipo dell'argomento non corrisponde esattamente al tipo del parametro, allora lo si promuove ® ® ® ® gli argomenti char, unsigned char e short vengono promossi ad int Un argomento unsigned short viene promosso ad int oppure a unsigned int gli argomenti float vengono promossi a double gli argomenti enumerazione vengono promossi al più piccolo tipo integrale che può contenere i valori di tutti gli enumeratori w Nell’ordine: int, unsigned int , long, unsigned long ® Gli argomenti boolean vengono promossi a int Laboratorio di Algoritmi e Strutture Dati 2001 -02 Corrispondenza per Promozione 28 enum colore { bianco = 100, nero = 1000, viola = 0xFFFFFFFF}; 1) void f(unsigned int); 2) void f(int); 3) void f(char); f(u'a'); f(0); f(true); f(viola); // corrisponde a 2 // corrisponde a 2 // corrisponde a 2 // corrisponde a 1 Laboratorio di Algoritmi e Strutture Dati 2001 -02 Esempi Corrispondenza per Promozione 29 Laboratorio di Algoritmi e Strutture Dati 2001/02 15 Lezione 7 Sovrapposizione di Funzioni ü Se il tipo dell'argomento non corrisponde al tipo del parametro, né esattamente né per promozione, allora si applicano le regole di conversone standard ® Conversioni intere w ogni argomento di tipo integrale o enumerazione è convertito in un altro tipo integrale ® Conversioni in virgola mobile w ogni argomento di tipo floating è convertito in un altro tipo floating ® Conversione virgola mobile-intero w ogni tipo integrale è convertito ad un tipo floating e viceversa Laboratorio di Algoritmi e Strutture Dati 2001 -02 Corrispondenza per Conversione Standard 30 ® ® Conversione di puntatori w 0 è convertito in un tipo puntatore w ogni tipo puntatore è convertito a void* Conversioni booleane w Ogni argomento di tipo intero, tipo in virgola mobile, enumeratore o puntatore è convertito al tipo bool Tutte le regole di conversione hanno lo stesso livello di precedenza Laboratorio di Algoritmi e Strutture Dati 2001 -02 Corrispondenza per Conversione Standard 31 Laboratorio di Algoritmi e Strutture Dati 2001/02 16 Lezione 7 Sovrapposizione di Funzioni 1) void f(unsigned int); 2) void f(float); 3) void f(void*); char *cp; f('a'); f(0); f(3.14); f(cp); // ambigua, corrisponde a 1 e 2 // ambigua , corrisponde a 1, 2, e 3 // ambigua, corrisponde a 1 e 2 // corrisponde a 3 Laboratorio di Algoritmi e Strutture Dati 2001 -02 Esempi: Corrispondenza per Conversione 32 ü Nel passaggio per riferimento l'argomento della funzione viene utilizzato per inizializzare il corrispondente parametro riferimento ® ® ® l'argomento deve essere dello stesso tipo del parametro nessuna conversione applicata l'argomento non può essere una variabile temporanea ü Se il parametro è definito come riferimento costante l'argomento può essere anche di tipo diverso Laboratorio di Algoritmi e Strutture Dati 2001/02 Laboratorio di Algoritmi e Strutture Dati 2001 -02 Conversioni per Parametri di tipo Riferimento 33 17 Lezione 7 Sovrapposizione di Funzioni ü Una funzione è candidata se ha lo stesso nome della funzione invocata e la sua dichiarazione è visibile nel punto della chiamata ® la sua dichiarazione appartiene ad uno dei namespace degli argomenti namespace LASD { class Matrice { … }; void f(Matrice&); } ® LASD::Matrice M; f(M); // void f(Matrice&) è una funzione candidata Laboratorio di Algoritmi e Strutture Dati 2001 -02 Calcolo delle Funzioni Candidate 34 ü Una funzione candidata è utilizzabile se i suoi parametri corrispondono per numero e tipo agli argomenti della chiamata ® oppure differiscono solo per parametri inizializzati per default void f(); void f(int); void f(double, double = 3.14); f(3.12) // funzioni utilizzabili: void f(int) // void f(double, double = 3.14) Laboratorio di Algoritmi e Strutture Dati 2001 -02 Calcolo Funzioni Utilizzabili 35 Laboratorio di Algoritmi e Strutture Dati 2001/02 18 Lezione 7 Sovrapposizione di Funzioni ü Per ogni funzione utilizzabile il compilatore calcola il tipo di corrispondenza tra parametri ed argomenti ü Per ogni coppia parametro-argomento viene valutato il tipo della sequenza di conversioni ® il tipo della sequenza è dato dal tipo della conversione peggiore contenuta nella sequenza ü La migliore funzione utilizzabile deve avere ® ® su ogni argomento una conversione non peggiore di quella di qualunque altra funzione utilizzabile su almeno un argomento una corrispondenza migliore di tutte le altre funzioni utilizzabili Laboratorio di Algoritmi e Strutture Dati 2001 -02 Calcolo della Migliore Funzione Utilizzabile 36 int arr[3]; void PutValues(const int *); int main() { //…. PutValues(arr); // 2 conversioni // 1) da array a puntatore // 2) conversione di qualificazione return 0; } Laboratorio di Algoritmi e Strutture Dati 2001 -02 Esempio di sequenza di conversioni 37 Laboratorio di Algoritmi e Strutture Dati 2001/02 19 Lezione 7 Sovrapposizione di Funzioni ü Una sequenza di conversioni è potenzialmente composta dalle seguenti conversioni, nell’ordine indicato: ® Trasformazioni di Lvalue ® Promozioni o conversioni standard ® Conversioni di qualificazione Laboratorio di Algoritmi e Strutture Dati 2001 -02 Possibile sequenza di conversioni 38 ü Per ogni coppia argomento-parametro assegna ® 1 per una corrispondenza esatta ® 2 per una corrispondenza per promozione ® 3 per una corrispondenza per conversione ® 4 per una corrispondenza definita dall'utente ü (i1, i2, …, in) < (j1, j2, …, j n) se esiste un k tale che i < jk ® k i ≤ jh ∀ h ≠ k ® h Laboratorio di Algoritmi e Strutture Dati 2001 -02 Calcolo della Migliore Funzione Utilizzabile 39 Laboratorio di Algoritmi e Strutture Dati 2001/02 20 Lezione 7 Sovrapposizione di Funzioni 1) void f(char*, int); 2) void f(int, int=0); 3) void f(unsigned int, double); 4) void f(char); f(0, 'a'); f(0, 3.14); f('a', 'b'); f(13u); // corrisponde a 2 // ambigua // corrisponde a 2 // ambigua Laboratorio di Algoritmi e Strutture Dati 2001 -02 Esempi Corrispondenza con più Parametri 40 Laboratorio di Algoritmi e Strutture Dati 2001/02 21