Sei sulla pagina 1di 83

Corso di Programmazione

a oggetti
Ereditariet
a.a. 2015/2016
Francesco Fontanella

Ereditariet
Meccanismo grazie al quale un oggetto
acquisisce le propriet di un altro oggetto.
Chiama in causa il concetto di classificazione: la
maggior parte della conoscenza resa pi
gestibile da classificazioni gerarchice.
Esempio
una mela rossa Delicious appartiene alla
classificazione mela, che a sua volta appartiene
alla classificazione frutta, che a sua volta si trova
nella classe pi estesa cibo.
Francesco Fontanella, Corso di Programmazione Orientata agli Oggetti
a.a. 2015/2016

Lereditariet consente di realizzare


relazioni tra classi di tipo generalizzazionespecializzazione
Una classe, detta base, realizza un
comportamento generale, comune ad un
insieme di entit, mentre le classi
cosiddette derivate (sottoclassi)
realizzano comportamenti specializzati
rispetto a quelli della classe base
Francesco Fontanella, Corso di Programmazione Orientata agli Oggetti
a.a. 2015/2016

Esempio
Tipo o classe base: Animale
Tipi derivati (sottoclassi): Cane, Gatto,
Cavallo,
Nel paradigma a oggetti, col meccanismo
dellereditariet ci si concentra sulla
creazione di tassonomie del sistema in
esame

Francesco Fontanella, Corso di Programmazione Orientata agli Oggetti


a.a. 2015/2016

Generalizzazione vs
Specializzazione
Generalizzazione: dal particolare al
generale
Specializzazione o particolarizzazione:
dal particolare al generale

Francesco Fontanella, Corso di Programmazione Orientata agli Oggetti


a.a. 2015/2016

SPECIALIZZAZIONE

GENERALIZZAZIONE
Francesco Fontanella, Corso di Programmazione Orientata agli Oggetti
a.a. 2015/2016

Veicolo

Veicolo Senza
Motore

Veicolo
A Motore

Motocicletta

Automobile

Autobus

Taxi

NOTA
Lo stesso sistema pu essere descritto da diverse tassonomie,
a seconda degli obiettivi
Esempio
Automobile
Automobile
Benzina
Berlina
Diesel
Station Wagon
Francesco Fontanella, Corso di Programmazione Orientata agli Oggetti
a.a. 2015/2016

Ereditariet e riuso
Il grande vantaggio dell'uso dell'ereditariet
legato al riuso del software.
Pu capitare infatti di disporre del codice di una
classe che non corrisponde esattamente alle
proprie esigenze. Anzich scartare del tutto il
codice esistente e riscriverlo, si pu seguire con
l'ereditariet un approccio diverso, costruendo una
nuova classe che eredita il comportamento di
quella esistente
Francesco Fontanella, Corso di Programmazione Orientata agli Oggetti
a.a. 2015/2016

10

classBuilding{
introoms;
intfloors;
floatarea;
public:
voidset_rooms(intr){rooms=r;};
voidset_floors(intf){floors=f;};
voidset_area(floata){area=a;};
intget_rooms(){returnrooms;};
intget_floors(){returnfloors;};
intget_area(){returnarea;};
};

Francesco Fontanella, Corso di Programmazione Orientata agli Oggetti


a.a. 2015/2016

11

Grazie all'ereditariet possibile creare


una classficazione generale che pu
essere incorporata in oggetti pi specifici.
Nella classe base vengono specificati gli
attribuiti e le funzioni comuni. Mentre le
classi derivate contengono solo gli attribuiti
specifici relativi alla particolare
sottoclasse.
Francesco Fontanella, Corso di Programmazione Orientata agli Oggetti
a.a. 2015/2016

12

derivata da

Class Building

classHouse:publicBuilding{
intbedrooms;
intbaths;
public:
voidset_bedrooms(intr){bedrooms=r;};
voidset_baths(intb){baths=b;};
intget_bedrooms(){returnbedrooms;};
intget_baths(){returnbaths;};
};
Francesco Fontanella, Corso di Programmazione Orientata agli Oggetti
a.a. 2015/2016

13

derivata da

Class Building

classSchool:publicBuilding{
intclassrooms;
intoffices;
public:
voidset_classrooms(intc){classrooms=c;};
voidset_offices(into){offices=o;};
intget_classrooms(){returnclassrooms;};
intget_offices(){returnoffices;};
};
Francesco Fontanella, Corso di Programmazione Orientata agli Oggetti
a.a. 2015/2016

14

#includehouse.h
#includeschool.h
main()
{
Househ;
Schools;

h.set_rooms(12);
h.set_floors(3);
h.set_area(300);
h.set_bedrooms(5);
h.set_baths(3);
s.set_rooms(46);
s.set_floors(2);
s.set_area(900);
s.set_offices(7);
s.set_baths(3);
.
.
}
Francesco Fontanella, Corso di Programmazione Orientata agli Oggetti
a.a. 2015/2016

15

La classe Persona
classPersona{
stringnome,cognome;
public:
Persona(stringn=,stringc=);
voidset_nome(stringstr){nome=str;}
voidset_cognome(stringstr){cognome=str;}
stringget_nome(){returnnome;}
stringget_cognome(){returncognome;}
};

Francesco Fontanella, Corso di Programmazione Orientata agli Oggetti


a.a. 2015/2016

16

La classe studente
classStudente{
stringnome,cognome;
intmatr;
public:
Studente(stringn=,stringc=,intm=0);
voidset_nome(stringstr){nome=str;}
voidset_cognome(stringstr){cognome=str;}
voidset_matr(intm){matr=m;}
stringget_nome(){returnnome;}
stringget_cognome(){returncognome;}
intget_matr(){returnmatr;}
voidshow();

Appartengono anche a persona

Francesco Fontanella, Corso di Programmazione Orientata agli Oggetti


a.a. 2015/2016

17

La nuova classe studente


classStudente:publicPersona{
intmatr;
public:
Studente(stringn="",stringc="",intm=0);

voidset_matr(intm){matr=m;}
intget_matr(){returnmatr;}
voidshow();
};

Francesco Fontanella, Corso di Programmazione Orientata agli Oggetti


a.a. 2015/2016

18

Osservazioni
Lereditarieta classica descrive una
relazione del tipo:
un (is-a)
ClassPersona

ClassStudente

Il diagramma pu essere letto cos:


uno studente una persona
Francesco Fontanella, Corso di Programmazione Orientata agli Oggetti
a.a. 2015/2016

19

Nell'esempio precedente la classe Persona


descrive campi e metodi comuni a tutte le persone
e quindi la classe base (quella pi generale).
Uno studente una (is-a) persona, quindi la classe
che lo modella eredita tutti i campi e metodi di
Persona (senza doverli riscrivere).
Alla classe studente vanno solo aggiunti i campi e i
metodi specifici per modellare correttamente gli
studenti ( una classe derivata, meno generale).

Francesco Fontanella, Corso di Programmazione Orientata agli Oggetti


a.a. 2015/2016

20

Specificatori di accesso
L'ereditariet viene dichiarata usando la sintassi:
classclasse_derivata:accessoclasse_base

La parola accesso specifica il tipo di accesso che la


classe derivata pu avere sui membri della classe
base. Esistono tre tipi di accesso:

Public;

Private;

Protected
Francesco Fontanella, Corso di Programmazione Orientata agli Oggetti
a.a. 2015/2016

21

Lo specificatore public
Quando lo specificatore di accesso public:
Tutti i membri pubblici della classe base
sono pubblici anche nella classe derivata.

I membri protetti della classe base sono


protetti anche in quella derivata.
I membri privati della classe base restano
privati, e non sono accessibili neanche da
parte dei membri della classe derivata.
Francesco Fontanella, Corso di Programmazione Orientata agli Oggetti
a.a. 2015/2016

22

classBase{
inti,j;
public:
voidset(inta,intb){i=a;j=b};
voidshow(){cout<<i<<<<j;};
};
classDerived:publicBase{
intk;
public:
Derived(inta){k=a;};
voidshowk(){cout<<k;};
voidsetk(){k=i;}// ERRORE!: i privato!
};
Francesco Fontanella, Corso di Programmazione Orientata agli Oggetti
a.a. 2015/2016

23

#includederived.h
intmain()
{
Derivedd(3);

// Accesso a membri della classe base


d.set(1,2);
d.show()

// uso di un membro della classe derivata


d.showk();

return0;
}
Francesco Fontanella, Corso di Programmazione Orientata agli Oggetti
a.a. 2015/2016

24

Lo specificatore private
Quando lo specificatore di accesso private:

Tutti i membri pubblici e protetti della classe


base sono privati nella classe derivata.
Ovviamente i membri privati continuano a
essere privati anche per i membri della
classe derivata

Francesco Fontanella, Corso di Programmazione Orientata agli Oggetti


a.a. 2015/2016

25

classBase{
inti,j;
public:
voidset(inta,intb){i=a;j=b};
voidshow(){cout<<i<<<<j;};
};
classDerived:privateBase{
intk;
public:
Derived(inta){k=a;};
voidshowk(){cout<<k;};
};
Francesco Fontanella, Corso di Programmazione Orientata agli Oggetti
a.a. 2015/2016

26

#includederived.h
main()
{
Derivedd(3);

d.set(1,2);// ERRORE!
d.show();// ERRORE!

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

27

Lo specificatore protected
I membri dichiarati protected non sono
accessibili dall'esterno
A parte un importante eccezione:
lo specificatore protected equivalente
allo specificatore private, nel senso
che tali membri sono accessibili solo da
parte dei membri della classe.

Francesco Fontanella, Corso di Programmazione Orientata agli Oggetti


a.a. 2015/2016

28

L'unica eccezione si verifica per le classi


derivate, in quanto i membri dichiarati
protected sono accessibili da parte delle
classi derivate
In pratica attraverso lo specificatore
protected il programmatore pu creare
membri della classe che sono privati, ma
che possono essere acceduti e modificati
dalle classi derivate.
Francesco Fontanella, Corso di Programmazione Orientata agli Oggetti
a.a. 2015/2016

29

classBase{
protected:
inti,j;// privato di base, ma accessibile da derived
public:
voidset(inta,intb){i=a;j=b};
voidshow(){cout<<i<<<<j;};
};
classDerived:publicBase{
intk;
public:

voidsetk(){k=i*j;};
voidshowk(){cout<<k;};

Setk pu accedere a i e j perch:


-- base ereditata come public;
-- i e j sono dichiarate come protected

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

30

#includederived.h
main()
{
Derivedd(2,3);
d.show();// membro della classe base

// membri della classe derivata


d.setk();
d.showk();
};

Francesco Fontanella, Corso di Programmazione Orientata agli Oggetti


a.a. 2015/2016

31

Specificatore protected:
ereditariet multipla
Esiste anche la possibilit che una classe
derivata sia a sua volta usata come classe
base per un ulteriore derivazione
In questo caso, tutti i membri protected
della classe base se ereditati come public
dalla prima classe derivata potranno
essere ereditati nuovamente come
protected dalla seconda classe derivata.
Francesco Fontanella, Corso di Programmazione Orientata agli Oggetti
a.a. 2015/2016

32

classBase{
protected:
inti,j;
public:
voidset(inta,intb){i=a;j=b};
voidshow(){cout<<i<<<<j;};
};
classDerived1:publicBase{
intk;
public:
voidsetk(){k=i*j;};
voidshowk(){cout<<k;};
};
classDerived2:publicDerived1{
intm;
public:
voidsetm(){m=ij;};
voidshowm(){cout<<m;};
};

Francesco Fontanella, Corso di Programmazione Orientata agli Oggetti


a.a. 2015/2016

33

#includederived.h
main()
{
Derived2d1,d2;
d1.set(2,3);//
d1.setk();//

d2.set(3,4);//
d2.setk();//
d1.show();//

membro di Base
membro di Derived1
membro di Base
membro di Derived1
membro di Base

d1.showk();// membro di Derived1


d2.setm();// membro di Derived2
d1.showm();// membro di Derived2
};
Francesco Fontanella, Corso di Programmazione Orientata agli Oggetti
a.a. 2015/2016

34

classBase{
protected:
inti,j;
public:
voidset(inta,intb){i=a;j=b;};
voidshow(){cout<<i<<""<<j;};
};
classDerived1:privateBase{
intk;
public:
voidsetk(){k=i*j;};//OK!
voidshowk(){cout<<k;};
};
classDerived2:publicDerived1{
intm;
public:
voidsetm(){m=ij;};// ERRORE!
voidshowm(){cout<<m;};
};

Francesco Fontanella, Corso di Programmazione Orientata agli Oggetti


a.a. 2015/2016

35

#includederived.h
main()
{
Derived1d1;
Derived2d2;
d1.set(2,3);// ERRORE!
d1.setk();
d1.show();// ERRORE!
d2.set(3,4);// ERRORE!
d2.setk();
d2.show();// ERRORE!
d2.showk();
d2.showm();
};
Francesco Fontanella, Corso di Programmazione Orientata agli Oggetti
a.a. 2015/2016

36

Ereditariet di una classe base


come protected
anche possibile ereditare una classe base
come protected.
In tal caso tutti i membri public e
protected della classe base diventano
membri protected della classe derivata.
Francesco Fontanella, Corso di Programmazione Orientata agli Oggetti
a.a. 2015/2016

37

classBase{
protected:
inti,j;
public:
voidset(inta,intb){i=a;j=b};
voidshow(){cout<<i<<<<j;};
};
classDerived1:protectedBase{
intk;
public:
voidsetk(){k=i*j;};
voidshowk(){cout<<k;};
};
classDerived2:publicDerived1{
intm;
public:
voidsetm(){m=ij;};// OK!
voidshowm(){cout<<m;};
};
Francesco Fontanella, Corso di Programmazione Orientata agli Oggetti
a.a. 2015/2016

38

#includederived.h
main()
{
Derivedd1,d2;
d1.set(2,3);// ERRORE!
d1.setk();
d1.show();// ERRORE!
d2.set(3,4);// ERRORE!
d2.setk();
d2.show();// ERRORE!
d2.showk();
d2.showm();
};
Francesco Fontanella, Corso di Programmazione Orientata agli Oggetti
a.a. 2015/2016

39

Accesso alle classi: modifiche


Se una classe ereditata come private, tutti i suoi
membri public e protected divengono private
nella classe derivata
possbile per, modificare in maniera selettiva, le
specifiche originali di uno o pi membri ereditati dalla
classe base.
Questa modifica pu essere fatta per mezzo della
keyword using
Francesco Fontanella, Corso di Programmazione Orientata agli Oggetti
a.a. 2015/2016

40

classBase{
protected:
inti,j;
public:
voidset(inta,intb){i=a;j=b;}
voidshow(){cout<<i<<""<<j;}
};
classDerived:privateBase{
intk;
public:
usingBase::show;
voidsetk(){k=i*j;}
voidshowk(){cout<<k;}
};
Francesco Fontanella, Corso di Programmazione Orientata agli Oggetti
a.a. 2015/2016

42

Overriding di metodi
classBase{
protected:
inti;
public:
voidshow(){cout<<"showdiBase:"<<endl;}
};
classDerived1:publicBase{
intj;
public:
voidshow(){cout<<"showdiDerived1:"<<endl;}
};
classDerived2:publicDerived1{
intk;
public:
voidshow(){cout<<"showdiDerived2:"<<endl;}
};
Francesco Fontanella, Corso di Programmazione Orientata agli Oggetti
a.a. 2015/2016

43

intmain(){
Baseb,*bp;
Derived1d1,*dp1;
Derived2d2;

b.show();
d1.show();
d2.show();
cout<<endl;

// Punto agli oggetti con bp...


bp=&b;
bp>show();

bp=&d1;
bp>show();

bp=&d2;
bp>show();
cout<<endl;
Francesco Fontanella, Corso di Programmazione Orientata agli Oggetti
a.a. 2015/2016

SEGUE...
44

// Punto agli oggetti con dp1...


dp1=&d1;
dp1>show();

dp1=&d2;
OUTPUT
dp1>show();
return0
}

showdiBase
showdiDerived1
showdiDerived2
showdiBase
showdiBase
showdiBase
showdiDerived1
showdiDerived1

Francesco Fontanella, Corso di Programmazione Orientata agli Oggetti


a.a. 2015/2016

45

Object slicing
Per quanto appena visto, possibile inizializzare un
oggetto della classe base con uno di una classe
derivata.
Ci che si ottiene che solo la parte base
dell'oggetto derivata viene assegnato. Si parla di
object slicing.
L'operazione inversa invece illegale: non
possibile assegnare ad un oggetto derivato un
oggetto della classe Base
Francesco Fontanella, Corso di Programmazione Orientata agli Oggetti
a.a. 2015/2016

46

intmain(){
Baseb,*bp;
Derived1d1,*dp1;
Derived2d2,*dp2;

// b e pb
b=d1;// OK
b=d2;// OK
bp=dp1;//
bp=dp2;//
bp=&b;//
bp=&d1;//
bp=&d2;//

OK
OK
OK
OK
OK

// d1 e dp1
d1=d2;// OK
dp1=dp2;// OK
dp1=&d1; // OK
dp1=&d2; // OK
Francesco Fontanella, Corso di Programmazione Orientata agli Oggetti
a.a. 2015/2016

SEGUE...
47

d1=b;// ERRRORE!
dp1=bp;// ERRRORE!
dp1=&b;// ERRRORE!
// d2 e dp2
dp2=&d2;// OK
d2=b;// ERRRORE!
d2=d1;// ERRRORE!
dp2=bp;// ERRRORE!
dp2=dp1;// ERRRORE!
dp2=&b;// ERRRORE!
dp2=d1;// ERRRORE!
return0;
}

Francesco Fontanella, Corso di Programmazione Orientata agli Oggetti


a.a. 2015/2016

48

Puntatori a tipi derivati


Quanto appena detto resta valido anche per i
puntatori
Va inoltre fatto notare che puntando ad un
oggetto della classe derivata con un
puntatore alla classe base possibile
accedere SOLO ai membri della classe base
che sono stati importati dalla classe base:
Francesco Fontanella, Corso di Programmazione Orientata agli Oggetti
a.a. 2015/2016

49

classBase{
protected:
inti;
public:
voidset_i(inta){i=a;}
};
classDerived1:publicBase{
protected:
intj;
public:
voidset_j(inta){j=a;}
};
classDerived2:publicDerived1{
intk;
public:
voidset_k(inta){k=a;}
};
Francesco Fontanella, Corso di Programmazione Orientata agli Oggetti
a.a. 2015/2016

50

intmain(){
Baseb,*bp;
Derived1d1;
Derived2d2;
bp=&b;
bp>set_i(0);

bp=&d1;
bp>set_i(0);//
bp>set_j(1);//

bp=&d2;
bp>set_i(0);//
bp>set_j(1);//
bp>set_k(1);//

return0;
}

OK!
ERRORE!

OK!
ERRORE!
ERRORE!

Francesco Fontanella, Corso di Programmazione Orientata agli Oggetti


a.a. 2015/2016

51

L'assegnazione di un indirizzo di un
oggetto di una classe derivata ad un
puntatore della classe base pu essere
fatto SOLO se la classe Base stata
ereditata come public, in caso contrario
l'assegnazione vietata

Francesco Fontanella, Corso di Programmazione Orientata agli Oggetti


a.a. 2015/2016

52

classBase{
protected:
inti;
public:
voidset_i(inta){i=a;}
intget_i(){returni;};
};
classDerived:privateBase{
intj;
public:
voidset_j(inta){i=a;}
intget_j(){returni;};
};

Francesco Fontanella, Corso di Programmazione Orientata agli Oggetti


a.a. 2015/2016

53

#includederived.h
main()
{

Base*bp;
Derivedd;

bp=&d;// ERRORE!
};

Francesco Fontanella, Corso di Programmazione Orientata agli Oggetti


a.a. 2015/2016

54

Accesso mediante casting


Con un puntatore alla classe Base
possibile accedere accedere alle funzioni
della classe derivata mediante casting:
intmain()
{
Base*bp;
Derivedd;

bp=&d;
.
.
((derived*)bp)>set_j(1);//OK
cout<<endl<<((derived*)bp)>get_j();//OK
return0;
};
Francesco Fontanella, Corso di Programmazione
a.a. 2015/2016

Orientata agli Oggetti

55

Aritmetica dei puntatori


importante ricordare che quando un
puntatore base punta ad un oggetto
derivato, l'incremento del puntatore non fa
in modo che questo punti all'oggetto
successivo, del tipo derivato.
Al contrario esso punter a quello che
dovrebbe essere l'oggetto successivo del
tipo base.
Francesco Fontanella, Corso di Programmazione Orientata agli Oggetti
a.a. 2015/2016

56

#includederived.h
main()
{
Base*bp;
Derivedd[2];

bp=d;
d[0].set_i(1);
d[1].set_i(2);

cout<<endl<<bp>get_i();
Equivale a
bp++;
bp=bp+sizeof(Base)

Visualizza
cout<<endl<<bp>get_i();
un valore casuale
};
Francesco Fontanella, Corso di Programmazione Orientata agli Oggetti
a.a. 2015/2016

57

Ereditariet multipla
Una classe derivata pu ricevere in eredit
anche due o pi classi base.
Per ereditare da pi classi base si deve
usare un elenco di classi separate da
virgole. Va inoltre utilizzato uno
specificatore per ogni classe ereditata.

Francesco Fontanella, Corso di Programmazione Orientata agli Oggetti


a.a. 2015/2016

58

classBase1{
protected:
intx;
public:
voidshowx(){cout<<x;};
};
classBase2{
protected:
inty;
public:
voidshowy(){cout<<y;};
};
Francesco Fontanella, Corso di Programmazione Orientata agli Oggetti
a.a. 2015/2016

59

Class Base1

Class Base2

classDerived:publicBase1,publicBase2{
.
.
public:
voidset(inti,intj){x=i;y=j;};
};
Francesco Fontanella, Corso di Programmazione Orientata agli Oggetti
a.a. 2015/2016

60

Costruttori, distruttori ed
ereditariet
Quando si usa l'ereditariet bisogna tenere
conto dei costruttori e distruttori
Infatti possibile che una classe base,
una classe derivata o entrambe
contengano una funzione costruttore e/o
distruttore

Francesco Fontanella, Corso di Programmazione Orientata agli Oggetti


a.a. 2015/2016

61

Vi sono due problemi principali derivanti


dall'uso di costruttori e distruttori quando si
usa l'ereditariet.
In quale momento vengono chiamate le
funzioni costruttore e distruttore della
classe base e di quella derivata?
Come fare per passare parametri alle
funzioni costruttore della classe base?

Francesco Fontanella, Corso di Programmazione Orientata agli Oggetti


a.a. 2015/2016

62

quando si crea un oggetto di una classe


derivata si chiama prima il costruttore della
classe base e poi quello della classe derivata.
Per quanto riguarda la distruzione. Accade
l'inverso: viene prima chiamato il distruttore
della classe derivata e poi quello della classe
base.
Questa scelta praticamente obbligata:
PERCH ?
Francesco Fontanella, Corso di Programmazione Orientata agli Oggetti
a.a. 2015/2016

63

classBase{
public:
Base(){cout<<"costruzionedibase"<<endl;}
~Base(){cout<<"distruzionedibase"<<endl;}
};
classDerived:publicBase{
public:
Derived(){cout<<"costruzionediderived"<<endl;}
~Derived(){cout<<"distruzionediderived"<<endl;}
};

Francesco Fontanella, Corso di Programmazione Orientata agli Oggetti


a.a. 2015/2016

64

#includederived.h
main()
{
Derivedd;

};

OUTPUT

costruzionedibase
costruzionediderived
distruzionedibase
distruzionediderived

Francesco Fontanella, Corso di Programmazione Orientata agli Oggetti


a.a. 2015/2016

65

Passaggio di argomenti
Nei casi in cui sono solo i costruttori della
classe derivata a richiedere uno o pi
argomenti, si usa la sintassi standard dei
costruttori parametrizzati.
Ma come possibile passare argomenti a una
funzione costruttore di una classe base?

Francesco Fontanella, Corso di Programmazione Orientata agli Oggetti


a.a. 2015/2016

67

La forma generale di dichiarazione estesa


di un costruttore di una classe derivata la
seguente:
costruttore_derivata(elencoargomenti):base1(elencoargomenti),
base2(elencoargomenti),...baseN(elencoargomenti)
{
// Corpo del costruttore derivato
.
.
.
}

Francesco Fontanella, Corso di Programmazione Orientata agli Oggetti


a.a. 2015/2016

68

classBase{
inti;
public:
Base(intx){i=x;cout<<"costruzionedibase,i:"<<i<<endl;}
~Base(){cout<<"distruzionedibase"<<endl;}
};
classDerived:publicBase{
intj;
public:
Derived(intx,inty):Base(y)
{j=x;cout<<"costruzionediderived,j:"<<j<<endl;}
~Derived(){cout<<"distruzionediderived"<<endl;}
};

Francesco Fontanella, Corso di Programmazione Orientata agli Oggetti


a.a. 2015/2016

69

#includederived.h
intmain()
{
Derivedd(3,4);

.
.

return0;
};

OUTPUT

costruzionedibase,i:4
costruzionediderived,j:3
distruzionediderived
distruzionedibase

Francesco Fontanella, Corso di Programmazione Orientata agli Oggetti


a.a. 2015/2016

70

classBase1{
inti;
public:
Base1(intx){i=x;cout<<costruzionedibase1;<<endl};
~Base1(){cout<<distruzionedibase;<<endl};
};
classBase2{
intk;
public:
Base2(intx){k=x;cout<<costruzionedibase2;<<endl};
~Base2(){cout<<distruzionedibase;<<endl};
};

Francesco Fontanella, Corso di Programmazione Orientata agli Oggetti


a.a. 2015/2016

71

Class Base1

Class Base2

classDerived:publicBase1,publicBase2{
intj;
public:
Derived(intx,inty,intz):Base1(y),Base2(z)
{j=x;cout<<costruzionediderived<<endl;};
~Derived(){cout<<distruzionediderived<<endl;};
};
Francesco Fontanella, Corso di Programmazione Orientata agli Oggetti
a.a. 2015/2016

72

importante comprendere che gli argomenti per il


costruttore della classe base vengono passati
attraverso gli argomenti del costruttore della classe
derivata.
Pertanto anche se il costruttore della classe
derivata non utilizza argomenti, ne dovr
comunque dichiarare uno se il costruttore della
classe base lo richiede.

Francesco Fontanella, Corso di Programmazione Orientata agli Oggetti


a.a. 2015/2016

73

Gli argomenti passati ai costruttori delle


classi base possono essere usati anche dal
costruttore della classe derivata
Esempio
classDerived:publicBase
intj;
public:
Derived(intx,inty):Base(x)
{j=x*y;
cout<<costruzionediderived<<endl;
}
};
Francesco Fontanella, Corso di Programmazione Orientata agli Oggetti
a.a. 2015/2016

74

Ereditariet: esempio
Supponiamo di avere a disposizione una classe
Lista
classList{
public:
voidList(){n=0;l=0;}
intsize()const;
intclear();
boolempty()const;
voidinsert(TipoValueval,intpos);
voidremove(intpos);
voidset(TipoValueval,intpos);
TipoValueget(intpos)const;
private:
nodo*l;
intn;
};
Francesco Fontanella, Corso di Programmazione Orientata agli Oggetti
a.a. 2015/2016

75

La classe Pila
// pila.h
#include"Lista.h"

classPila:privateLista{
Public:
usingLista::size;
usingLista::clear;
usingLista::empty;
Pila(){}
voidpush(TipoValueval){insert(val,0);}
TipoValuetop()const{returnget(0);}
TipoValuepop(){
TipoValuetmp=get(0);
remove(0);

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

76

La classe Coda
// coda.h
#include"Lista.h"

classCoda:privateLista{
Public:
usingLista::size;
usingLista::clear;
usingLista::empty;
Pila(){}
voidadd(TipoValueval){insert(val,n);}
TipoValuehead()const{returnget(0);}
TipoValuetake(){
TipoValuetmp=get(0);
remove(0);

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

77

Ereditariet: operatore di
assegnazione
Deve essere realizzato per classi con
estensione dinamica. A differenza degli altri
operatori NON viene ereditato.
Possono verificarsi 4 diversi casi

SEGUE...
Francesco Fontanella, Corso di Programmazione Orientata agli Oggetti
a.a. 2015/2016

78

N la classe base n la derivata


implementano operator=
Il compilatore utilizza lop. = di default
(bit a bit) per entrambi le classi.
Solo la classe base implementa operator=

Il compilatore utilizza loperatore di


assegnazione della classe base e
loperatore di default per la parte derivata
Francesco Fontanella, Corso di Programmazione Orientata agli Oggetti
a.a. 2015/2016

79

Solo la classe derivata implementa


operator=
Viene richiamato SOLO operator= della
derivata che responsabile di assegnare
TUTTO loggetto derivato.
Il compilatore NON assegna il sotto-oggetto
base (non viene chiamato loperatore di
default della classe base).

Francesco Fontanella, Corso di Programmazione Orientata agli Oggetti


a.a. 2015/2016

80

Sia la classe base che la derivata


implementano operator=():
Loperatore della classe derivata deve
esplicitamente richiamare loperatore di
assegnazione della classe base
Derived&operator=(constDerived&d){
Base::operator=(d);
// codice per la parte derivata
return*this;
}
Francesco Fontanella, Corso di Programmazione Orientata agli Oggetti
a.a. 2015/2016

81

Ereditariet: costruttore di copia


La classe base non sa della presenza della
derivata.
Possono verificarsi gli stessi 4 casi visti in
precedenza per l'operatore di assegnazione
il compilatore si comporta allo stesso modo
Francesco Fontanella, Corso di Programmazione Orientata agli Oggetti
a.a. 2015/2016

82

N la classe base n la derivata implementano


il Costruttore di Copia (CC):
Il compilatore usa il CC di default (copia bit a
bit) per entrambi
Solo la classe base implementa il CC:
Il compilatore usa il CC della classe base per
la parte base ed effettua la copia membro a
membro per la parte propria
SEGUE...
Francesco Fontanella, Corso di Programmazione Orientata agli Oggetti
a.a. 2015/2016

83

Solo la classe derivata implementa il CC:


Viene richiamato SOLO il CC della derivata
che responsabile di costruire TUTTO
loggetto derivato. Il compilatore NON chiama
il CC di default della classe base.
Sia la classe base che la derivata implementano
il CC
Il CC della classe base deve essere chiamato
mediante lista di inizializzazione dal CC della
classe derivata. Viene costruito prima il sottooggetto base e poi quello derivato.
Francesco Fontanella, Corso di Programmazione Orientata agli Oggetti
a.a. 2015/2016

84

Composizione
Un'altra possibilit per riusare il codice gi
scritto da altri quella di implementare una
classe che ha come dati membro degli
oggetti di altre classi,
Questa modalit di riuso detta
composizione (composition).

Francesco Fontanella, Corso di Programmazione Orientata agli Oggetti


a.a. 2015/2016

85

Esempio
#include"point.h"
Passaggio di parametri ai

costruttori di copia di p1 e p2
classRetta{
Pointp1,p2;
public:
Retta(Pointo1,Pointo2):p1(o1),p2(o2){}
floatpendenza(){
return(p2.gety()p1.gety())/(p2.getx()p1.getx());
}
};

Francesco Fontanella, Corso di Programmazione Orientata agli Oggetti


a.a. 2015/2016

86

#include"retta.h"
intmain(){

Pointp1(1,1),p2(2,2);
Rettar(p1,p2);
cout<<"Pendenza"<<r.pendenza()<<endl;
}

NOTA
In generale, la composizione implica una relazione
del tipo: has-a (ha-un)

Francesco Fontanella, Corso di Programmazione Orientata agli Oggetti


a.a. 2015/2016

87