Sei sulla pagina 1di 29

Corso di Programmazione

a oggetti
Programmazione generica

a.a. 2015/2016
Francesco Fontanella

Programmazione generica
Consente la definizione di una classe (o
funzione) senza che venga specificato il tipo
di dato di uno o pi dei suoi membri (o dei
suoi parametri)
La sua utile quando il codice non dipende
dal tipo di dato da elaborare
Esempi:
ADT (pila, coda, ecc)
Algoritmi di ordinamento
Francesco Fontanella, Corso di Programmazione a Oggetti
a.a. 2015/2016

Templates
Le classi (funzioni) per i quali uno o + tipi di
dati non sono specificati sono dette:
templates
I templates definiscono delle classi
(funzioni) cosiddette generiche, o anche
parametriche,
Questo codice deve poi essere istanziato
dall'utente per produrre del codice che lavori
con specifici tipi di dato
Francesco Fontanella, Corso di Programmazione a Oggetti
a.a. 2015/2016

template<classT>
Tfunz(Tpar)
{
Tvar1,var2,varN;
.
.
.
returnvar1;
}
intmain()
{
inti;
floatf;
charc;
funz(i);
funz(f);
funz(c);

return0;
}

intfunz(intpar)
{
intvar1,var2,varN;
.
.
.
returnvar1;
}
floatfunz(floatpar)
{
floatvar1,var2,varN;
.
.
.
returnvar1;
}
charfunz(charpar)
{
charvar1,var2,varN;
.
.
.
returnvar1;
}

Francesco Fontanella, Corso di Programmazione a Oggetti


a.a. 2015/2016

<class T> indica che T


un parametro da istanziare
template<classT>Tfind_max(Tv[],intn)
{
inti,m;

m=0;

for(i=1;i<n;++i)
if(v[i]>v[m])
m=i;

returnv[m];
}

Per il tipo T deve essere


stato definito loperatore >

intmain()
{
inti,vi[],n;
floatf,vf[];
charc,str[];
.
.

i=find_max(vi,n);
f=find_max(vf,n);
c=find_max(str,n);
return0;
}

Francesco Fontanella, Corso di Programmazione a Oggetti


a.a. 2015/2016

Istanziare un template
Una volta definito, un template pu essere usato
specificando i tipi di dato da istanziare
Esempio
template<classT>
voidswap(T&x,T&y)
{Tt=x;
x=y;
y=t;
}

Pu essere istanziata con tipi differenti:


swap<int>
swap<float>
Francesco Fontanella, Corso di Programmazione a Oggetti
a.a. 2015/2016

inti=3,j=4;
swap<int>(i,j);
.
.
floatf=4.0,g=5.0;
swap<float>(f,g);
Conoscendo i tipi degli
argomenti, il compilatore in
grado dinferire listanziazione
corretta
inti=3,j=4;
swap(i,j);// uses swap<int>
.
.
floatf=4.0,g=5.0;
swap(f,g);// uses swap<float>
Francesco Fontanella, Corso di Programmazione a Oggetti
a.a. 2015/2016

Templates di classi
template<classT>
classMyclass{
Tvar1,var2,varN;
.
.
Tfunz1()
voidfunz2(Tpar1,);
.
.
};

Per istanziare una classe generica necessaro


specificare il tipo di T:
Myclass<int>mi;
Myclass<float>mf;
Francesco Fontanella, Corso di Programmazione a Oggetti
a.a. 2015/2016

10

Parametri di un template
template<classT,intsize=100>
classVector{
Tv[size];
public:
T&operator[](inti);
Non tutti i parametri devono
};
essere tipi generici
template<classT,intsize=100>
T&Vector<T,size>::operator[](inti){
if(i>=0&&i<size);
returnv[i];
elsecerr<<endl<<ERRORE!;
}
Vector<int,50>ivect;
Vector<double>dvect;
Francesco Fontanella, Corso di Programmazione a Oggetti
a.a. 2015/2016

11

template<classT,classU>
classPair{
Tx1;
Un template pu avere uno o
Ux2;
pi parametri
public:
Pair(Ta1,Ua2):x1(a1),x2(a2){}
};
Pair<string,int>p1("deep",6);
cout<<p1.x1<<""<<p1.x2<<endl;

NOTA
Le funzioni membro di una classe template sono
istanziate solo se usate
Francesco Fontanella, Corso di Programmazione a Oggetti
a.a. 2015/2016

12

Esempio: stack di interi


classStack{
public:
Stack(){top=0;}
~Stack();
voidpush(intval);{top=newNodo(val,top);}
intpop()
private:
Nodo*top;
};
classNodo{
public:
Nodo(intv,Nodo*n):value(v),next(n){}
intgetVal(){returnvalue;}
Nodo*get_next(){returnnext;}
intget_value(){returnvalue;}
private:
Nodo*next;
intvalue;
};
Francesco Fontanella, Corso di Programmazione a Oggetti
a.a. 2015/2016

13

Stack::~Stack()
{
while(top)
pop();
}

intStack::pop(){
intv;
Nodo*tmp;
if(top){
v=top>get_value();
tmp=top;
top=top>get_next();
deletetmp;

returnv;
}elsecerr<<endl<<"ERRORE!";
}
Francesco Fontanella, Corso di Programmazione a Oggetti
a.a. 2015/2016

14

Stack generico
template<classK>classNodo{
public:
Nodo(Kv,Nodo*n):value(v),next(n){}
Kget_val(){returnvalue;}
Nodo*get_next(){returnnext;}
private:
Nodo*next;
Kvalue;
};
template<classT>classStack{
public:
Stack(){top=0;}
~Stack();
voidpush(Tval){top=newNodo<T>(val,top);}
Tpop();
private:
Nodo<T>*top;
Nodo va istanziato,
};
perch generico!
Francesco Fontanella, Corso di Programmazione a Oggetti
a.a. 2015/2016

15

template<classU>Stack<U>::~Stack(){
while(top)
pop();
}
template<classZ>ZStack<Z>::pop(){
Zv;
Nodo<Z>*tmp;
if(top){
v=top>getVal();
tmp=top;
top=top>getNext();
deletetmp;

returnv;
}elsecerr<<endl<<"ERRORE!";
}

NOTA
Per le diverse funzioni, anche di una stessa classe, posso usare
lettere diverse per i template e classi
Francesco Fontanella, Corso di Programmazione a Oggetti
a.a. 2015/2016

16

#include<stack.h>
intmain(){
Stack<int>si;
Stack<float>sf;
si.push(1);
sf.push(3.0);
cout<<endl<<si.pop();
cout<<endl<<sf.pop();

return0;
}

OUTPUT
> 1
> 3.0

Francesco Fontanella, Corso di Programmazione a Oggetti


a.a. 2015/2016

17

Nodo Generico
#ifndefNODE_H
#defineNODE_H
template<classT>
classNode{
public:
//Costruttore
Node(Tx):next(0),value(x){}
//FunzioniGET
Node<T>*get_next()const{returnnext;}
Tget_value()const{returnvalue;}
//FunzioniSET
voidset_next(Node<T>*ptr){next=ptr;}
voidset_value(Tval){value=val;}
private:
Tvalue;
Node*next;
friendclassListIterator<T>;// Vedi dopo...
friendclassList<T>;
};
#endif
Francesco Fontanella, Corso di Programmazione a Oggetti
a.a. 2015/2016

20

Lista Generica
#ifndefLIST_H
#defineLIST_H
template<classT>
classList{
public:
List():n(0),l(0){};
~List();
voidappend(Tx);
constT&operator[](intpos)const;
intsize()const{returnn;}
protected:
Node<T>*l;
intn;
friendclassListIterator<T>;
};

Francesco Fontanella, Corso di Programmazione a Oggetti


a.a. 2015/2016

21

Cast Type Overloading


In C++, oltre che dei normali operatori, possibile anche
l'overloading del casting ,
Esempio
classCents
{
private:
intm_nCents;
public:
Cents(intnCents=0){m_nCents=nCents;}

//Overloadedintcast
operatorint(){returnm_nCents;}
L'overloading

intGetCents(){returnm_nCents;}
voidSetCents(intnCents){m_nCents=nCents;}
};
Francesco Fontanella, Corso di Programmazione a Oggetti
a.a. 2015/2016

sul casting

23

intmain()
{
Centsc(7);
inta;
a=c;

diventa

a=Cents::int(&c)

cout<<a;

return0;
}

Francesco Fontanella, Corso di Programmazione a Oggetti


a.a. 2015/2016

24

Il Cast Type Overloading il meccanismo


che consente:
.
.
ifstramins(input.txt);

if(ins){
diventa
.
.

if(ios::bool)

Francesco Fontanella, Corso di Programmazione a Oggetti


a.a. 2015/2016

25

Iteratore sulla lista


#ifndefLISTITER_H
#defineLISTITER_H
#include"list.h"
template<classT>
classListIterator
{
public:
ListIterator(constList<T>&list):l(list),cur(list.l){}
T&operator*(){returncur>value;}
// Incremento prefisso
Node<T>*operator++(){returncur==0?0:cur=cur>next;}
// Incremento postfisso
Node<T>*operator++(inti);
//T&operator*(){returncur>value;}
voidrewind(){cur=l.l;};
operatorbool()const{returncur;}
private:
constList<T>l;
Node<T>*cur;
};
#endif
Francesco Fontanella, Corso di Programmazione a Oggetti
a.a. 2015/2016

26

Incremento postfisso
dell'iteratore
Node<T>*operator++(inti)
{
Node<T>*tmp=0;

if(cur){
tmp=cur;
cur=cur>next;
}

returntmp;
}
Francesco Fontanella, Corso di Programmazione a Oggetti
a.a. 2015/2016

27

#include<iostream>
#include"List.h"
#include"ListIterator.h
constintmax=1000;
intmain()
{
List<int>list,i;

for(i=0;i<max;++i)
list.append(i);

// uso inefficiente!
for(i=0;i<MAX;i++)
cout<<list[i];
// iterazione efficiente
ListIterator<int>it(list);
while(it){
cout<<*it<<"";

it++;
}
return0;
}

Francesco Fontanella, Corso di Programmazione a Oggetti


a.a. 2015/2016

28

Compilazione di template
Il compilatore non in grado di generare
codice oggetto quando vede una
definizione di template
Le istanze specifiche per un determinato
tipo, possono essere prodotte solo quando
i template vengono effettivamente utilizzati

Francesco Fontanella, Corso di Programmazione a Oggetti


a.a. 2015/2016

29

Per generare una qualsiasi istanza il


compilatore deve accedere al codice
sorgente che definisce il template
C++ standard definisce due modelli per la
compilazione del codice dei templates:
compilazione per inclusione (supportata
da tutti i compilatori)
compilazione separata (supportata solo
da alcuni)
Francesco Fontanella, Corso di Programmazione a Oggetti
a.a. 2015/2016

30

Compilazione per inclusione


La compilazione di template richiede che
negli header file (file .h) vengano inclusi
anche le definizioni delle funzioni
(implementazione)
A tal fine, bisogna inserire una direttiva
#include nel header file per inserire in
questultimo le definizioni contenute nel file
dimplementazione
Francesco Fontanella, Corso di Programmazione a Oggetti
a.a. 2015/2016

32

demo.h
#ifndefDEMO_H
#defineDEMO_H
template<classT>intconfrontare(constT&,constT&);
// altre dichiarazioni
.
.
#include"demo.cpp"
#endif

demo.cpp

template<classT>intconfrontare(constT&a,constT&b)
{
if(a<b)
return1;
if(b<a)
return1;
return0;
}
// altre definizioni
.
.
Francesco Fontanella, Corso di Programmazione a Oggetti
a.a. 2015/2016

33

Osservazioni
scrivere una funzione generica implica
pensare in astratto, evitando le
dipendenze da tipi di dato, costanti
numeriche, ecc.
Una definizione di funzione template
solo un modello e non produce
effettivamente codice
Francesco Fontanella, Corso di Programmazione a Oggetti
a.a. 2015/2016

34

Il template un generatore automatico


di funzioni specifiche
I templates tendono a generare un
codice eseguibile grande, poich
duplicano codice

Francesco Fontanella, Corso di Programmazione a Oggetti


a.a. 2015/2016

35