PROGRAMMAZIONE GENERICA�Template functions �e overloading di operatori
3^ INFORMATICO - IIS PASCAL�DIPARTIMENTO INFORMATICA
2
ARGOMENTI
3
DEFINIZIONE
Per programmazione “generica” si intendono una serie di �pratiche atte a definire strutture e funzioni che possono essere utilizzati con variabili di tipi diversi senza necessità�di ridefinizione
“Questo approccio, introdotto nel linguaggio ML nel 1973,[1][2] permette di scrivere codice generico, del quale possono essere auto-generate multiple versioni specializzate che differiscono solo per i tipi di dati trattati, riducendo così la necessità di scrivere codici essenzialmente duplicati.”[Wikipedia]
Template functions
Cos'è una "funzione template" ?
Scopriamolo con un esercizio...
Immaginiamo di voler scrivere una funzione �void scambia(int, int) che riceve due variabili
intere e ne scambia il valore
benissimo, andiamo avanti…
Cos'è una "funzione template" ?
Scopriamolo con un esercizio...
Immaginiamo di voler scrivere una funzione �void scambia(float, float) che riceve due variabili
float e ne scambia il valore
Ottimo lavoro!
andiamo avanti…
Cos'è una "funzione template" ?
Scopriamolo con un esercizio...
Immaginiamo di voler scrivere una funzione �void scambia(string, string) che riceve due variabili
string e ne scambia il valore
Wow…
e sono tre...
andiamo avanti…
Cos'è una "funzione template" ?
Scopriamolo con un esercizio...
Immaginiamo di voler scrivere una funzione �void scambia(double, double) che riceve due variabili
double e ne scambia il valore
Sono tutte uguali!!
Cambia solo il tipo !
ne servirebbe una generica…
Come si fa???
Programmazione generica
C++ mette a disposizione la sintassi per creare funzioni generiche
Per queste si deve specificare il comportamento �senza preoccuparsi del tipo.
Unica attenzione:
tutte le operazioni all'interno della funzione devono essere legali rispetto al tipo generico
legali significa che il compilatore deve sapere come si esegue una certa operazione per quel certo tipo di dato
template<typename T>
return_type function_name(T var_name, <var_list>) {
code...
}
Programmazione generica
Riscriviamo la nostra funzione scambio con la programmazione generica
NOTA: nella funzione template si usa solo l'assegnazione che è ben definita sia per gli int che per i float
template<typename T>
void scambia(T& x, T& y) { // per riferimento
T tmp = x;
x = y;
y = tmp;
}
int main() {
int a = 2; int b = 3;
scambia(a, b);
cout << " A = " << a << " B = " << b << endl;
float c = 2.5; float d = 3.6;
scambia(c, d);
cout << " C = " << c << " D = " << d << endl;
}
OUTPUT:
A = 3 B = 2
C = 3.6 D = 2.5
Programmazione generica : esercizio
Scrivere una funzione generica occorrenze (template function) che riceve
e restituisce un numero intero delle occorrenze di E in T
La funzione deve essere utilizzabile con il seguente codice
producendo il seguente output
int vettint[ ] {1,2,3,3,2,3,4,3};
int oc1 = occorrenze(vettint, 3, 8);
cout << "Il numero 3 è presente " << oc1 << " volte\n";
string s[ ] {"ciao", "come", "state", "come", "oggi", "come", "ieri"};
string s1 = "come";
int oc2 = occorrenze(s, s1, 7);
cout << "La stringa 'come' è presente " << oc2 << " volte\n";
�OUTPUT:
Il numero 3 è presente 4 volte�La stringa 'come' è presente 3 volte
Programmazione generica : soluzione
La programmazione generica ci consente di passare un array di elementi di tipo qualsiasi e un elemento dello stesso tipo da confrontare.
NOTA: nella funzione template si usa l’operatore di confronto che è ben definito sia per gli int che per le stringhe
template<typename T>
int occorrenze(T x[], T elem, int size) { // il passaggio per array è sempre per riferimento
int cont = 0;
for (int i = 0; i<size; i++) {
if (x[i] == elem) cont++;
}
return cont;
}
Programmazione generica : esercizi
Overloading di operatori
Overloading di operatori
Parlando di template functions abbiamo evidenziato che tutte le operazioni all'interno della funzione devono essere legali rispetto al tipo generico
In alcuni casi succederà che l’operazione della funzione generica NON sia di default permessa per un certo tipo dato
Come possiamo fare?
Dobbiamo fare in modo che il compilatore sappia come interpretare un operatore su un tipo dato nuovo
Overloading di operatori
Facciamo l’esempio della funzione generica differenza
template<typename T>
T differenza(T a, T b) {
return a-b;
}
int main() {
int a = 5;
int b = 3;
cout << differenza(a, b) << endl;
return 0;
}
�OUTPUT:
2
Overloading di operatori
Facciamo l’esempio della funzione generica differenza
template<typename T>
T differenza(T a, T b) {
return a-b;
}
int main() {
int a = 5;
int b = 3;
cout << differenza(a, b) << endl;
string s = "Ciao";
string t = "Raga";
cout << differenza(s, t) << endl;
return 0;
}
�OUTPUT:
/home/giulio/Documenti/Didattica/Scuola/Didattica/Dispense/01_Informatica/__3_INFO/Template_functions/3INFO_overloading_base/main.cpp|24|error: no match for ‘operator-’ (operand types are ‘std::__cxx11::basic_string<char>’ and ‘std::__cxx11::basic_string<char>’)|
Overloading di operatori
Facciamo l’esempio della funzione generica differenza
template<typename T>
T differenza(T a, T b) {
return a-b;
}
string operator-(string x, string y) {
return "Uhm! che operazione bizzarra!!!";
}
int main() {
int a = 5;
int b = 3;
cout << differenza(a, b) << endl;
string s = "Ciao";
string t = "Raga";
cout << differenza(s, t) << endl;
return 0;
}
�OUTPUT:
2
Uhm! che operazione bizzarra!!!
Overloading di operatori
Esercizio:
definisci l’operatore * per permettere la moltiplicazione fra stringa�e intero
es:
string s = “ciao”;
string t = s*3;
t deve essere ciaociaociao
10 minuti…
Overloading di operatori
Esercizio:
definisci l’operatore - per permettere la differenza fra due stringhe �dove si intenda la differenza carattere per carattere
Si assumano le due stringhe della stessa lunghezza
es:
string s = “otto”;
string t = “abba”;
s - t deve essere nrrn
10 minuti…