1 of 20

PROGRAMMAZIONE GENERICA�Template functions �e overloading di operatori

3^ INFORMATICO - IIS PASCAL�DIPARTIMENTO INFORMATICA

2 of 20

2

ARGOMENTI

  • Concetto di programmazione generica
  • Definizione di funzione template
  • Overloading di operatori

3 of 20

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]

4 of 20

Template functions

5 of 20

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…

6 of 20

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…

7 of 20

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…

8 of 20

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???

9 of 20

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...

}

10 of 20

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

11 of 20

Programmazione generica : esercizio

Scrivere una funzione generica occorrenze (template function) che riceve

  • un array A di elementi di tipo T
  • un elemento E di tipo T
  • un intero pari alla dimensione dell'array A

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

12 of 20

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;

}

13 of 20

Programmazione generica : esercizi

  1. Scrivi una funzione template ordina per ordinare un vettore qualsiasi in senso ascendente o discendente
  2. scrivi una funzione template colonnaMassima che prende in input una matrice di elementi qualsiasi e restituisce l'indice della colonna per la quale è massima la somma�hint: qual è il valore di riferimento per i tipi generici??? soluzione
  3. scrivi una funzione template isOrdinato che prende un array generico e la sua dimensione e restituisce True se l'array è ordinato, False altrimenti

14 of 20

Overloading di operatori

15 of 20

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

16 of 20

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

17 of 20

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>’)|

18 of 20

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!!!

19 of 20

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…

soluzione

20 of 20

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…

soluzione