Funzioni template
Le funzioni template consentono di scrivere funzioni generiche in cui è possibile parametrizzare anche il tipo dei valori passati. Al momento della chiamata il compilatore istanzia una funzione dove i tipi parametrizzati vengono sostituiti con il tipo degli argomenti della funzione.
Esempio:
// Definizione di un template
template <typename T>
T Massimo(T a, T b){
return (a>b)?a:b;
}
. . .
double x = 10.67, y = 9.84;
// Chiamata di un template
cout << Massimo(x,y) << endl;
La funzione Massimo() è una funzione template che
possiede due parametri, a e b,
di tipo T, dove T è un tipo
parametrico.
Al momento della chiamata il compilatore istanzia una funzione in cui T
è sostituito con double.
Classi template
Analogamente alle funzione template è possibile definire delle classi generiche, ovvero che possono contenere data member e member function di qualsiasi tipo.
Esempio:
// Definizione di una classe template
template
class Elemento{
public:
Elemento(); // costruttore
void SetMember(T a);
T GetMember();
private:
T val;
};
. . .
// Dichiarazione di un oggetto
Elemento
Quando viene istanziato un oggetto di questa classe, il compilatore sostituisce il parametro T con il tipo specificato tra parentesi angolari, in questo caso string.
Container vector
Questa particolare classe template (dichiarata nell'header file <vector>) consente di creare collezioni omogenee di oggetti di qualsiasi tipo. I vector possono essere impiegati in modo analogo ai comuni vettori C++ e possiedono diversi costruttori.
Esempio:
vector
vector
vector
In questo esempio vInt è un vector
di 100 elementi interi, vDouble è costituito da 10
elementi inizializzati a 0 e vChar è un vector
di char che non contiene elementi.
Per aggiungere un nuovo elemento in fondo a un vector
si può impiegare il metodo push_back():
vChar.push_back('A') ;
Per accedere a un elemento si può usare il suo indice:
cout << vDouble[5] << endl;
Container list
Questo container (dichiarato nell'header file <list>) consente di implementare con facilità liste (doubly linked list) che possono contenere elementi di qualsiasi tipo. Un esempio di dichiarazione di una lista di stringhe è:
list <string> elenco;
Analogamente ai vector, per aggiungere un nuovo elemento in coda a una lista si può impiegare il metodo push-back():
elenco.push_back(" Andrea") ;
Il metodo pop_back(), invece, permette di rimuovere l'ultimo elemento della lista. Esistono inoltre dei metodi che danno facoltà di effettuare analoghe operazioni con gli elementi di testa: push_front(), per l'inserimento, e, per l'eliminazione.
Container map
È un container associativo (dichiarato nell'header file <map>)
che permette di associare a ogni elemento inserito una chiave.
La chiave è un particolare valore che consente di mantenere ordinati gli
elementi del contenitore e di renderne più rapido l'accesso.
La dichiarazione di un container map richiede di specificare, nell'ordine,
il tipo della chiave e quello dell'elemento associato:
map <string, int> agen;
Analogamente ai vettori, l’inserimento e l'accesso agli elementi può avvenire specificando tra parentesi quadre, anziché un indice, la chiave dell'elemento:
// Associa 14 alla chiave "Ugo"
agen["Ugo"]=14;
cout <<agen["Ugo"]; // stampa 14
Iteratori
Gli iteratori fanno accedere agli elementi dei container con analoghe modalità, indipendentemente dalla loro struttura interna. Grazie agli iteratori è possibile elencare sequenzialmente tutti gli elementi di un container, individuare un elemento specifico e scrivere algoritmi generici che manipolano insiemi diversi di dati.
Quando si dichiara un iteratore occorre specificare a quale container appartiene:
vector <int>::iterator i;
Dopo questa dichiarazione è possibile accedere a qualsiasi elemento di un vector di interi, per esempio:
i = vet.begin();
cout << *(i + 5);
La prima istruzione inizializza l’iteratore i con la posizione del primo
elemento del vector vet; la seconda visualizza il
contenuto del 6° elemento.
Si noti l'uso dell'operatore di indirezione, come per i normali puntatori.
Algoritmi find
Questo algoritmo generico (header file <algorithm>) consente di individuare un elemento all'interno di un intervallo specificato. Il valore ritornato è il suo iteratore;
Esempio:
i = find(c.begin(), c.end(), 2);
if(i != c.end())
. . .
find cerca 2 in tutto il container c. Se l’iteratore ritornato non corrisponde a quello che punta oltre l'ultimo elemento (c.end()) allora l'elemento è stato trovato.
Algoritmo replace
La funzione template replace() (header file <algorithm>) cerca un elemento nell’intervallo definito da due iteratori di un container e (se lo trova) lo sostituisce
con l'elemento specificato.
Esempio:
replace(c.begin(), c.end(), 21, 99);
replace cerca l'elemento contenente il valore 21 in tutto il container c. Se l'elemento viene trovato sarà sostituito con il nuovo valore, 99.
Algoritmo copy
copy (header file <algorithm>) copia gli elementi del container sorgente compresi tra i due iteratori specificati nel container di destinazione a partire dall'iteratore elencato come terzo argomento.
Esempio:
copy(c1.begin(), c1.end(),
c2.begin());
La dimensione del container di destinazione deve essere sufficiente per contenere gli elementi copiati.
Algoritmo sort
L'algoritmo sort (header file <algorithm>) ordina gli elementi di un container compresi tra i due iteratori specificati. Per default la disposizione sarà in ordine ascendente (dal più piccolo al più grande):
sort(c.begin(), c.end()) ;
Se si desidera un altro criterio di ordinamento è possibile specificare la funzione che confronta due elementi:
sort(c.begin(), c.end(), Decresc);
Se il criterio è soddisfatto la funzione deve tornare il valore boolean true, altrimenti false.