edutecnica

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 el;

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 vInt(100);
vector vDouble(10, 0.0);
vector vChar;

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.