Si è già accennato nel cap.1 ad una delle principali novità introdotte dal linguaggio
C++: l'Ereditarietà. Con un esempio tratto dal mondo animale, è stato evidenziato
come i concetti possano essere organizzati in modo gerarchico, mediante un processo di
derivazione.
Vediamo un altro esempio: consideriamo il concetto di Persona.
Esso avrà degli attributi come Nome, Età, Sesso tanto per citarne alcuni.
Da tale entità possiamo derivarne molte altre:
ad esempio, una Persona può essere Studente, Lavoratore o Pensionato. Ciascuna di queste entità
eredita le caratteristiche dell'entità Persona (ha cioè un Nome, un'Età, un Sesso) ed in più
ne aggiunge altre: per esempio, un Lavoratore avrà un'Anzianità di Lavoro,
una Sede di lavoro, etc.
A sua volta dall'entità Lavoratore possiamo derivarne altre:
infatti, un Lavoratore può essere Impiegato, Professionista, Artigiano,
e così via il procedimento logico potrebbe continuare.
Per rappresentare graficamente tale processo di derivazione, è utile ricorrere ad una struttura
ad Albero come in Fig. 4.1, proprio come avviene per l'Albero Genealogico.
Trasferendo tutto ciò alla programmazione, con l'Ereditarietà è possibile rappresentare in modo
efficiente dati e funzioni, evitando ridondanze e ottimizzando la scrittura dei programmi,
mediante una riusabilità del codice.
In C++ l'esempio precedente può essere implementato nel modo seguente:
#define MAXCHAR 15 class Persona { char Nome[MAXCHAR]; char Sesso; short Eta; public: Persona(); ~Persona(); void MostraDati(); } class Lavoratore : public Persona { short Anzianità; char Sede[MAXCHAR]; public: Lavoratore(); ~Lavoratore(); }Il codice delle funzioni membro è stato omesso perchè distoglierebbe l'attenzione dalla sintassi usata per realizzare la derivazione.
class nome_classeDerivata : etichetta nome_classeBase { codice }La classe Lavoratore eredita i dati privati della classe base Persona, ovvero le variabili Nome, Sesso, Età, aggiungendone nuovi.
L'etichetta può essere public, protected o private. L'etichetta protected introduce un
ulteriore livello nel meccanismo di sicurezza del C++, intermedio fra private e public:
in effetti, tale etichetta ha un senso solo se la classe in cui è presente sarà
successivamente derivata, ossia all'interno della stessa classe i membri private e protected
hanno lo stesso livello di protezione. Il loro comportamento si differenzia solo nei
confronti di eventuali classi derivate dove i protetti della classe base sono accessibili
mentre i privati no.
A seconda del valore dell'etichetta nella classe derivata, si ha un diverso comportamento verso i
dati membro della classe base.
Si possono presentare i seguenti casi:
Finora è stato preso in esame il caso in cui, a partire da una classe, sia possibile derivare
una o più classi, ognuna delle quali discende, quindi da una sola classe.
Il C++ consente anche un tipo di derivazione in cui una classe deriva da più classi. Ad esempio,
un Medico può essere sia Impiegato (in Ospedale) che Professionista, secondo lo schema seguente:
Dal punto di vista sintattico, si scrive:
class Impiegato { . . . . } class Professionista { . . . . } class Medico : public Impiegato,protected Professionista { . . . . }dove ogni classe base può essere derivata con differente modalità.
Quando viene istanziato un oggetto di una classe derivata, viene automaticamente
richiamato prima il costruttore di default delle eventuali classi base e poi il
costruttore della classe derivata in esame.
Il costruttore di una classe derivata può invocare costruttori delle classi base diversi
da quelli di default, esplicitando tale chiamata nella riga di codice relativa
al costruttore della classe derivata.
Vediamo un esempio:
class X { . . . } class Y:public X { . . . } Y OggettoY;In tal caso, è invocato prima il costruttore di default della classe base, ossia X(), e poi Y().
class Y:public X,public Z { . . . }In tal caso, sono invocati dapprima i costruttori di default delle classi base, nell'ordine in cui esse sono state dichiarate, cioè X(), Z() e infine Y().
class Y:public X,public Z { . . . } Y::Y(parametri):X(parametri),Z(parametri) { . . . }I costruttori sono invocati nell'ordine specificato nella linea di inizializzazione.
![]() Precedente |
![]() Home page |
![]() Successivo |