Derivazione di Classi
Derivazione di Classi
l’operazione di ereditarietà della programmazione ad
oggetti
ü La classe derivata può utilizzare tutti i dati ed i
metodi non privati della classe base come propri
elementi
Lezione 14
®
non c’è bisogno di riscrivere i metodi ereditati dalla classe
base, a meno che non debbano essere modificati
ü Il livello di accesso di un membro della classe può
essere privato, pubblico e protetto
®
i membri protetti non sono visibili dall’esterno della classe
ma sono ereditabili
Laboratorio di Algoritmi e Strutture Dati 2000-01
ü Il meccanismo della derivazione di classi implementa
Derivazione di Classi
Costruzione di Nuovi Tipi per
Composizione
ü La definizione di una classe derivata richiede la
ü Avremmo potuto anche definire la classe Window
class Window : public Video {
protected:
short origine_x, origine_y;
public:
void trasla(int, int); // nuovo metodo
char dammi(int, int); // ridefinizione
…
};
come contenente un oggetto Video
class Window2 {
Video V;
short origine_x, origine_y;
public:
…
};
Window2 W;
// la larghezza della finestra è contenutra in W.V.larghezza
2
3
Derivazione Singola e Multipla
ü Dichiarazione del template di classe list di LEDA
ü Ogni classe può specificare una o più classi base
class dlink;
class dlist {
dlink* h;
dlink* t;
int count;
….
};
template <class T>
class list : public dlist { … };
Laboratorio di Algoritmi e Strutture Dati 2000-01
Esempio
4
Laboratorio di Algoritmi e Strutture Dati
2001-02
da cui ereditare dati e metodi
ü L’insieme delle classi e le relazioni di derivazione
formano un grafo di derivazione
®
®
®
se ogni classe ha una sola classe base il grafo è un
albero
se le classi hanno più classi base il grafo è un DAG
il grafo di derivazione non può mai contenere cicli
ü Ogni classe del grafo contiene tutti gli elementi
che sono comuni a tutte le sue classi derivate
Laboratorio di Algoritmi e Strutture Dati 2000-01
specifica del nome delle classi da cui devono
essere ereditati dati e metodi. All’interno della
classe devono essere definiti i membri aggiuntivi
Laboratorio di Algoritmi e Strutture Dati 2000-01
Definizione di una Classe
Derivata
Laboratorio di Algoritmi e Strutture Dati 2000-01
1
5
1
Derivazione di Classi
Esempio Derivazione Singola
Esempio Derivazione Multipla
rettangolo
Panda
Orso
Felino
Pesce
OrsoBianco
Grizzly
Yoghi
6
ü I membri della classe base rappresentano
®
Insieme delle operazioni supportate da tutte le classi
derivate
w L’utente opererà solo sull’interfaccia della classe base
w Se l’implementazione dipende dalla classe derivata la funzione
è dichiarata virtuale (virtual )
®
Insieme dei dati comuni a tutte le classi derivate
w Evita di replicare le definizioni in ciascuna classe derivata
w Se le classi derivate devono accedere ad un membro dato è
dichiarato protected
7
Esempio Definizione AnimaleZoo
class AnimaleZoo {
public:
AnimaleZoo(char*, char*, short);
~AnimaleZoo();
virtual void disegna();
void localizza();
void informa();
protected:
char* nome;
char* file;
short gabbia;
short cont;
};
Laboratorio di Algoritmi e Strutture Dati 2000-01
Definizione di una Classe Base
8
®
®
Calcolo del perimetro
Settaggio del colore di sfondo e di quello del bordo
ü L’implementazione dei metodi per il calcolo
dell’area e il disegno del poligono dipendono dal
tipo della poligono
ü Ogni poligono è rappresentato da
®
®
®
Lista dei vertici
Colore di sfondo
Colore del bordo
9
Interfaccia Pubblica di Poligono
Laboratorio di Algoritmi e Strutture Dati 2000-01
Definizione della classe Poligono
ü Tutti i tipi di poligoni hanno in comune tre metodi
Laboratorio di Algoritmi e Strutture Dati 2000-01
rombo
Uccello
Laboratorio di Algoritmi e Strutture Dati 2000-01
quadrato
cerchio
AnimaleZoo
Estinzione Erbivoro
10
Laboratorio di Algoritmi e Strutture Dati
2001-02
class Poligono {
public:
Poligono();
Poligono(int N, vector<Punto>&);
// Crea un poligono con N lati memorizzati nel vettore
virtual double area() const;
double perimentro() const;
void setta_sfondo(colore);
// Non implementato
void setta_bordo(colore)
// Non implementato
virtual void disegna() const; // Non implementato
…
};
Laboratorio di Algoritmi e Strutture Dati 2000-01
poligono
Laboratorio di Algoritmi e Strutture Dati 2000-01
figura
11
2
Derivazione di Classi
Laboratorio di Algoritmi e Strutture Dati 2000-01
double Poligono::perimetro() const {
double ris=0.0;
for(int i=0; i<_numLati; i++)
ris += _lunghezza(_punti[i], _punti[(i+1) % _numLati]);
return ris;
}
12
13
Definizione di una Classe
Derivata
ü All’interno
della classe devono essere
definiti
®
I membri aggiuntivi
®
I metodi che devono essere modificati
14
class Quadrato : public Poligono {
public:
…
void disegna();
double area();
};
class Rettangolo : public Poligono {
public:
…
void disegna();
double area();
protected:
double _altezza, larghezza;
};
double Quadrato::area() {
double _lato =
_lunghezza(_vertici[0], _vertici[1]);
return _lato * _lato;
double Rettangolo::area() {
return _altezza * _larghezza;
}
}
15
Accesso con Operatore di Scope
ü Un oggetto di una classe derivata contiene un sotto-
ü I membri ereditati continuano a far parte di un
®
Contiene tutti i membri non-static della classe base
ü La classe derivata può accedere ai dati non privati della
classe base come se fossero propri membri
ü I dati privati sono presenti ma non visibili
®
Il compilatore segnala un accesso illegale
Quadrato *q;
q→ area();
// accede a Quadrato::area()
q→ perimetro(); // accede a Poligono::perimetro()
Laboratorio di Algoritmi e Strutture Dati 2000-01
Accesso ai Membri Ereditati
oggetto della sua classe base
16
Laboratorio di Algoritmi e Strutture Dati
2001-02
Laboratorio di Algoritmi e Strutture Dati 2000-01
definizione di una classe derivata
richiede la specifica del nome delle classi da
cui devono essere ereditati dati e metodi
Laboratorio di Algoritmi e Strutture Dati 2000-01
ü La
Classi Derivate da Poligono
oggetto della classe base e possono essere anche
referenziati tramite l’operatore di scope ::
q→ Poligono::perimetro();
ü L’operatore di visibilità è necessario quando
® il membro ereditato è stato ridefinito nella classe derivata
® quando la classe eredita da classi base diverse membri con lo stesso
nome
Laboratorio di Algoritmi e Strutture Dati 2000-01
class Poligono {
…
protected:
int _numLati;
vector<Punto> _vertici;
color _sfondo;
color _bordo;
_lunghezza(const Punto&, const Punto&);
};
Laboratorio di Algoritmi e Strutture Dati 2000-01
Definizione metodo: perimetro
Rappresentazione Poligono
17
3
Derivazione di Classi
Accesso ai Membri Protetti della
Classe Base
bool Quadrato::ConfrontaLati(const Poligono* pp) {
int MieiLati = _NumLati;
int SuoiLati = pp→
→ _NumLati;
// ERRORE, accesso a dato protected
// Versione corretta: SuoiLati = pp→ GetLati();
return (MieiLati == SuoiLati );
}
/* ConfrontaLati e GetLati dovrebbero essere definite
nelle classi Poligono e Quadrato */
accesso anche ai membri di B ereditati da altre classi
class AnimaleZoo {
friend void prezzo(AnimaleZoo&);
int valore;
…
};
class Orso : public AnimaleZoo {
int eta;
…
};
void prezzo(AnimaleZoo& a) {
Orso tmp;
tmp.valore;
// legale
tmp.eta;
// illegale
}
18
ü Un oggetto di una classe derivata contiene sotto-
class AnimaleZoo {
friend void prezzo(AnimaleZoo&);
…
};
class Primati : public AnimaleZoo {
friend class AnimaleZoo;
friend void capacitaParola(Primati&);
…
};
La funzione prezzo non può accedere ai dati privati di Primati
La funzione capacitaParola non può accedere ai membri
privati della classe base AnimaleZoo
Laboratorio di Algoritmi e Strutture Dati 2000-01
ü La relazione di amicizia non è transitiva
gli amici degli amici non sono miei amici
19
Inizializzazione delle Classi
Derivate
Derivazione ed Amicizia
®
oggetti ereditati dalle sue classi base
®
Questi sotto-oggetti sono inizializzati dai loro costruttori
ü L’inizializzazione di un oggetto della classe derivata
avviene in tre passi. Sono invocati:
2.
I costruttori delle classi base, per inizializzare i sotto-oggetti
ereditati
I costruttori delle classi membro definiti nella classe
3.
Il costruttore della classe derivata
1.
1. Questo accade quando un dato membro è di tipo classe
20
Inizializzazione delle Classi
Derivate
Il sotto-oggetto viene identificato tramite il nome della classe
base
ü I
costruttori delle classi base sono chiamati
nell’ordine in cui le classi sono specificate nella lista
di derivazione
Quadrato::Quadrato(const double lato): Poligono(lato,4) {};
ü Il costruttore di Quadrato non deve inizializzare i dati
ereditati da Poligono:
® Non si potrebbe modificare la classe Poligono
senza modificare anche il codice di Quadrato
Laboratorio di Algoritmi e Strutture Dati 2000-01
®
21
Costruttori Classe Poligono
ü Gli argomenti da passare ai costruttori delle classi
base sono indicati nella lista di inizializzazione
Laboratorio di Algoritmi e Strutture Dati 2000-01
Rispetto ad altri oggetti della classe base si comporta come un
oggetto esterno (non può accedere alla parte protetta)
Laboratorio di Algoritmi e Strutture Dati 2000-01
®
ü Una funzione amica di una classe B ha privilegio di
22
Laboratorio di Algoritmi e Strutture Dati
2001-02
class Poligono {
public:
Poligono();
protected:
Poligono(const vector<Punto> &);
Poligono(double L, int N)
// crea un poligono di N lati lunghi L
};
Poligono::Poligono() : _NumLati(0), _vertici(), _Sfondo(Bianco),
_Bordo(Nero) { }
Poligono::Poligono(double val, int lati) : _NumLati(lati), _vertici(lati),
_Sfondo(Rosso), _Bordo(Azzurro) { // calcola vertici }
Poligono::Poligono(const vector<Punto> & pol) : _vertici(pol),
_Sfondo(Verde), _Bordo(Giallo) {_NumLati=pol.size(); }
Laboratorio di Algoritmi e Strutture Dati 2000-01
membri protetti del suo sotto-oggetto della classe base
Laboratorio di Algoritmi e Strutture Dati 2000-01
ü Un oggetto di una classe derivata può accedere solo ai
Derivazione ed Amicizia
23
4
Derivazione di Classi
Costruttori per Copia di Classi
Derivate
Costruttori Classi Derivate
®
®
il costruttore di default inizializza membro a membro
l’inizializzazione delle parti ereditate dalle classi base è
fatta dai costruttori per copia delle classi base
i costruttori sono chiamati nell’ordine in cui sono
specificate le classi base nella lista di derivazione
ü Se la classe contiene la propria versione del
costruttore per copia questo costruttore dovrà
assegnare i valori ai dati ereditati dalle classi base
(inizializzate per default)
ü Analogo per l’assegnamento
24
Distruttori Classi Derivate
Laboratorio di Algoritmi e Strutture Dati 2000-01
Il compilatore invoca automaticamente i
distruttori dei membri e delle classi base
® Non c’è bisogno di invocare esplicitamente
questi distruttori
®
25
Esempio: la Classe Panda
ü Quando un oggetto di una classe
derivata termina il suo tempo di vita
deve essere distrutto
ü Consideriamo come viene inizializzato un oggetto
di tipo Panda
®
®
®
®
®
chiama il costruttore di AnimaleZoo
chiama il costruttore di Orso
chiama il costruttore di Erbivoro
chiama il costruttore di Estinzione
chiama il costruttore di Panda per assegnare valori
agli elementi specifici di Panda
ü Le chiamate ai distruttori sono in ordine inverso
26
Livello di Accesso della
Derivazione
ü Una
Il livello di accesso determina la visibilità dei membri
ereditati all’interno della classe derivata
ü Ogni membro non privato della classe base ha il
livello di accesso più restrittivo tra quello che aveva
nella classe base e quello della derivazione
®
®
®
Derivazione public: ogni elemento ereditato conserva il
livello di accesso della classe base
Derivazione protected: tutti i membri ereditati sono
protected
Derivazione private: tutti i membri ereditati sono private
Laboratorio di Algoritmi e Strutture Dati 2000-01
®
27
Derivazione Pubblica
ü Ogni derivazione ha un livello di accesso che può
essere public, private o protected
Laboratorio di Algoritmi e Strutture Dati 2000-01
®
Laboratorio di Algoritmi e Strutture Dati 2000-01
Rettangolo::Rettangolo (double d1, double d2, vector<Punto>& v)
: Poligono(v ) {
_altezza = d1;
_larghezza = d2;
}
inizializzato per copia anche se non esiste la versione
del costruttore per copia
28
Laboratorio di Algoritmi e Strutture Dati
2001-02
derivazione public implementa
relazione di specializzazione (isa)
®
®
una
tutti i metodi pubblici della classe base fanno parte
dell’interfaccia pubblica della classe derivata
è possibile convertire un oggetto della classe
derivata nella classe base
ü La derivazione pubblica è usata per ereditare
l’interfaccia pubblica della classe base
®
La classe derivata può essere utilizzata allo stesso
modo delle classi basi, più altri modi specifici
Laboratorio di Algoritmi e Strutture Dati 2000-01
Rettangolo::Rettangolo () {_altezza = _larghezza = 0;}
ü Un oggetto di una classe derivata può essere
Laboratorio di Algoritmi e Strutture Dati 2000-01
class Rettangolo {
public:
Rettangolo();
Rettangolo (double, double, vector<Punto>&);
…
};
29
5
Derivazione di Classi
Derivazione Privata
Eccezioni della Derivazione
®
Nessun membro pubblico della classe base fa parte
dell’interfaccia pubblica della classe derivata
per convertire un oggetto della classe derivata nella classe
base serve un cast
ü La
derivazione privata è usata per ereditare
l’implementazione della classe base
®
®
La classe derivata contiene tutti i membri non privati della
classe base
Possibile ottenere lo stesso risultato inserendo nella classe
derivata un membro dato della classe base (contenimento)
accesso diverso da quello definito dalle regole standard
®
consentire che un metodo di una classe ereditata privatamente sia public
ü Non è possibile assegnare ad un membro un livello di accesso più
permissivo di quello che aveva nella classe base
template <class T>
class Stack : private Array<T> {
public:
Array<T>::lenght;
// la funzione lenght di Array<T> è public
…
};
30
31
Risoluzione dei Nomi in una
Gerarchia di Classi
ü Ogni oggetto, riferimento o puntatore ad una classe
ü Il campo di visibilità di una classe derivata è
derivata può essere convertito in un oggetto,
riferimento o puntatore ad una delle sue classi base
void ruota(const Poligono&);
…
rettangolo q(10, 20);
ruota(q); // accede solo ai dati ereditati da Poligono
ü Ogni puntatore ad un membro di una classe base può
essere convertito in un puntatore ad un membro di
una classe derivata pubblicamente
Laboratorio di Algoritmi e Strutture Dati 2000-01
Conversioni Standard e
Derivazioni
contenuto nei campi di visibilità delle sue classi
base
ü Risoluzione dell’identificatore prova contenuto
nella funzione Panda::letargo()
®
cerca nel campo di visibilità di Panda::letargo
®
cerca nel campo di visibilità di Panda
®
cerca contemporaneamente nel campo di visibilità di Orso,
Erbivoro ed Estinzione
®
cerca nel campo di visibilità di AnimaleZoo
®
cerca nel campo di visibilità globale
Laboratorio di Algoritmi e Strutture Dati 2000-01
®
Laboratorio di Algoritmi e Strutture Dati 2000-01
contenimento (hasa)
Laboratorio di Algoritmi e Strutture Dati 2000-01
ü E’ possibile specificare per un membro ereditato un livello di
ü Una derivazione private implementa una relazione di
ü Se trova più soluzioni contemporaneamente da errore di
32
ambiguità
33
ü Una classe derivata eredita tutti i metodi della sua
classe base tranne i costruttori, il distruttore e
l’operatore di assegnamento
ü Non è possibile sovrapporre all’operatore ereditato
dalla classe base una versione locale alla classe
derivata, anche se ha firma differente
®
il nome dell’operatore è risolto sulla base dei campi di
visibilità, senza tener conto dei tipi
Laboratorio di Algoritmi e Strutture Dati 2000-01
Ereditarietà di Operatori
34
Laboratorio di Algoritmi e Strutture Dati
2001-02
6