167
1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI [email protected]

1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI [email protected]

Embed Size (px)

Citation preview

Page 1: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

1

Introduzione alla programmazione ad oggetti

E.Mumolo, DEEI

[email protected]

Page 2: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

2

Paradigmi di programmazione

È un punto di vista della programmazione Alcuni paradigmi

Programmazione imperativa (lista di istruzioni da eseguire, es. Fortran, C, C++, Java ….) Programmazione non strutturata Programmazione strutturata

Programmazione dichiarativa (condizioni logiche, es. Prolog, Lisp …)

Programmazione procedurale Programmazione ad oggetti …

Page 3: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

3

Architetture software

Programmazione procedurale

Funzione principale

Sotto-funzione 1 Sotto-funzione 2

Sotto-funzione 1.2 Sotto-funzione 2.1 Sotto-funzione 2.2Sotto-funzione 1.1

Page 4: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

4

Programmazione non strutturata Problema:

if(90<A<100)and(25<B<100)or(80<A<89)and(50<B<100)or(70<A<79)and(75<B<100) then “ACCETTA”

Usando GOTO:

Non accetta accetta

A>90

A>80

A>70 B>50

B>25

B>75

SI

SI

SI

SI

SI

SI

Page 5: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

5

Programmazione strutturata

Codice realizzato mediante combinazione di tre strutture

Tutti gli algoritmi possono essere realizzati mediante le tre strutture

Page 6: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

6

Programmazione strutturata

A>90

A>80

A>70 B>50

B>25

B>75

SI

SI

SI

SI

SI

SI

NNNN AAA

Page 7: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

7

Programmazione strutturata - pseudocodiceif(A>90)

thenif(B>25)then

Accettaelse

Nonaccettafi

elseif(AZ80)then

if(B>50)then

Accettaelse

Nonaccettafi

elseif(A>70)then

if(B>75)then

Accettaelse

Nonaccettafi

fifi

fi

Page 8: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

8

Programmazione procedurale Modello procedurale

Il mondo della programmazione viene visto come un sistema di processi

Alcuni temi tipici del modello procedurale: Processi, sequenze di esecuzione Diagrammi di flusso Programmazione top-down Programmazione strutturata Algoritmi=strutture dati + programmazione strutturata Tradizionali linguaggi strutturati: Fortran, Pascal, C … Operazioni effettuate sui dati inviate alle procedure e alle

funzioni sistemi software validi ed efficienti per basse complessità MA : ad alte complessità si evidenzia un cedimento del sistema

Una modifica di una struttura dati ha grandi effetti sul sistema campo di visibilità delle strutture dati

Riusabilita’ nei linguaggi procedurali

Page 9: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

9

Esempio: conto corrente Programmazione procedurale:

Decomposizione funzionale del problema Divisione del problema in moduli Progetto struttura dati, esempio:

Implementazione delle funzioni per operare con i dati, esempio: Deposito(ID,#) Preleva(ID,#) CalcolaInteressi(ID) …

Numero correntistaNome correntistaSaldoNumero operazioni

… …

ID correntista

Page 10: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

10

Approccio orientato agli oggetti: OOA

metodologia generale pensare e rappresentare problemi usando

concetti del mondo reale oggetti: rappresentano proprietà e

comportamenti in una unica entità I modelli possono essere implementati

usando un linguaggio di programmazione, un sistema di gestione di archivi, in hardware etc…

Page 11: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

11

Alcune differenze tra OO e procedurale

OOP dati e comportamento contenuti in un oggetto singolo

Procedurale dati e comportamento separati OOP divide il problema in oggetti separati che

realizzano azioni relazionandosi con altri oggetti Vantaggi proncipali di OOP:

Dati e operazioni incapsulati in un oggetto Quando viene creato un nuovo tipo di oggetto, non è

necessario modificare le implementazioni precedenti Piuttosto, il nuovo oggetto eredita alcune caratteristiche

precedenti Programmi OO sono di più semplice manutenzione

Page 12: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

12

Esempio: conto corrente Programmazione procedurale:

L’attenzione del programmatore è concentrata sulle funzioni che manipolano i dati!

Ma: l’attenzione di un correntista è più concentrata sui dati che sulle funzioni!

Inoltre: Chiunque può modificare i dati (se i dati

sono visibili) Funzioni e dati entità separate

Punto di vista tradizionale: valore=CalcolaInteressi(ID);

funzione argomentovalore di ritorno

Page 13: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

13

Esempio: conto corrente Programmazione ad oggetti:

L’attenzione del programmatore è concentrata sui dati non sulle funzioni Dati e funzioni NON sono entità separate programma ad oggetti: insieme di oggetti cooperanti, che sono istanze di un

tipo di dati astratto Esempio di tipo di dati astratto per gestire un conto corrente:

ContoCorrenteNumero correntistaNome correntistaSaldoNumero operazionideposita(valore)preleva(valore)calcolaInteressi()incrementaNumeroOperazionileggiNumeroOperazioni()

dati

funzioni

Page 14: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

14

Esempio: conto corrente Programmazione ad oggetti:

Un particolare Conto Corrente è una ‘istanza’ del tipo do dati astratto

Le funzioni sono attivate mediante messaggi.

Un particolare ContoCorrente: cosa è visibile dall’esterno?

Punto di vista ad oggetti: valore=ID CalcolaInteressi();

oggetto funzionevalore di ritorno messaggio

Oggetto:ContoCorrente Dati privati:

Numero correntistaNome correntistaSaldo Dati protetti: numero operazioni

Dati e funzioni pubbliche:Deposita Preleva leggiNumeroOperazioni CalcolaInteressi

interfaccia

Page 15: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

15

Esempio: conto corrente Utilizzo dell’oggetto:

oggettoContoCorrente

Messaggio:‘deposita(x)’

Messaggio:‘leggiNumeroOperazioni()’

Page 16: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

16

Cenni di UML

UML è un linguaggio (Unified Modeling Language)

Fornisce i costrutti per lo sviluppo di sistemi software: Analisi dei requisiti Analisi e progetto OO Modellazione dei componenti Modellazione della struttura e della configurazione

Modello espresso mediante diagrammi grafici

Page 17: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

17

Cenni di UML Diagrammi di UML

Diagramma dei casi d’uso: elenca i casi d’uso del sistema e le loro relazioni

Diagramma delle classi: struttura dati degli oggetti e loro relazioni

Diagramma degli oggetti: mostra un insieme di oggetti e loro relazioni

Diarammi di interazione: interazioni tra gli oggetti durante scenari di funzionamento

Diagrammi di stato e attività: descrive gli stati di un oggetto e le sequenze eventi-azioni-transizioni

Diagramma dei componenti: descrive l’architettura fisica del sistema

Diagramma di distribuzione: struttura del sistema hardware e allocazione dei vari moduli software

Page 18: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

18

Cenni di UML

Diagrammi dei casi d’uso: Rappresentano le modalità di utilizzo del sistema da parte

degli attori del sistema Descrivono l’interazione tra attori e sistema, la logica

interna Un attore

Spedisce o riceve messaggi dal sistema, o scambia informazioni con esso

Esegue i casi d’uso (funzionalitè percepita da un attore, e sempre attivato da un attore)

Corrisponde ad una classe, non ad un oggetto

Page 19: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

19

Cenni di UML

Diagramma dei casi d’uso in una biblioteca

Attore: il cliente

Attore: il bibliotecario

restituzione

prestito

prenota

Cancella la prenotazione

Page 20: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

20

Simboli usati per la visibilità

ContoCorrente-Numero correntista-Nome correntista-Saldo#Numero operazioni+deposita(valore)+preleva(valore)+calcolaInteressi()-incrementaNumeroOperazioni+leggiNumeroOperazioni()

CCNumeroCorrentista : intNomeCorrentista : char [10]NumeroOperazioni : int

incrementaNumeroOperazioni()deposita()preleva()calcolaInteressi()leggiNumeroOperazioni()

UML Tool di Reverse eng.

• Tipo di dati astratto=classe• istanza di un tipo di dati astratto = oggetto • incapsulamento = data hiding = fornisce un livello di astrazione attraverso le funzoni

Non c’è struttura dati separata: operazioni e struttura dati integrate in una singola entità

Page 21: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

21

Modelli orientati agli oggetti Modello ad oggetti

Il mondo viene visto come un sistema di cose

Comportamento visibile

Un oggetto

Stato interno nascosto

Oggetto = stato + comportamento + identità

Page 22: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

22

Esempio di organizzazione per oggettiOggetto automobile

Oggetto Carrozzeria Oggetto Motore

peso = automobile peso()

peso = carrozzeriapeso() + motorepeso()

Page 23: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

23

Le classi

Classificazione: Oggetti con gli stessi attributi e con gli stessi

comportamenti sono raggruppati in classi Classe astrazione che descrive delle proprietà Una classe descrive un insieme di oggetti

individuali. Un oggetto è una istanza della classe

Ogni istanza ha valori diversi degli attributi Le istanze di una classe condividono i nomi degli

attributi e le operazioni

Page 24: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

24

Approccio orientato agli oggetti Esempio di classi:

PezzoScacchi (una Torre è un oggetto della classe) Attributi:

Colore, Altezza, Posizione Operazioni:

Muove Poligono (un Triangolo è un oggetto della classe)

Attributi: Vertici, ColoreBordi, ColoreInterno

Operazioni: Disegna, Cancella, Muove

Bicicletta (la mia bicicletta è un oggetto della classe) Attributi:

DiametroRuote, Altezza, Materiale Operazioni:

Muove, Ripara, Pulisci

Page 25: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

25

Passi per la modellazione OO

Identificare gli oggetti Identificare il comportamento degli oggetti Identificare le relazioni tra gli oggetti Realizzare gli oggetti: raggruppare in classi le strutture

dati ed i comportamenti

Page 26: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

26

Approccio orientato agli oggetti

Caratteristiche di un oggetto: Attributi (struttura dati) Comportamento

Caratteristiche richieste da un approccio orientato agli oggetti: Identità (identity) Polimorfismo (polymorphism) Ereditarietà (inheritance)

Page 27: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

27

Approccio orientato agli oggetti

Identità: oggetti distinti: ogni oggetto ha la sua identità anche se i

loro attributi sono identici Oggetti: entità concrete (es. un file in un file system) o

concettuali (es.: una politica di schedulazione) Oggetti del mondo reale (esempio): due mele – anche se

dello stesso colore e forma sono due oggetti distinti -, due gemelli, una persona, un oscilloscopio …

Oggetti definiti mediante un linguaggio di programmazione (esempio): un albero binario, una tabella …

Page 28: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

28

Approccio orientato agli oggetti Polimorfismo:

La stessa operazione si comporta diversamente in diverse classi (es. operazione Muovi nella classe PezzoScacchi e Bicicletta).

La specifica implementazione di una operazione è chiamata metodo.

Polimorfismo=diversi metodi per operatore In un linguaggio orientato agli oggetti il linguaggio

seleziona automaticamente il metodo corretto L’utente può non conoscere quanti metodi

implementano un operatore

Page 29: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

29

Approccio orientato agli oggetti Ereditarietà:

Creazione di una gerarchia tra le classi Metodo di progetto bottom-up: una super-classe

viene definita in modo generico e poi viene perfezionata via via in sotto-classe

La super classe fattorizza le proprietà comuni di diverse classi

Una sotto-classe eredita tutte le proprietà della sua superclasse e aggiunge altre proprietà

Normalmente le proprietà della superclasse non sono ripetute in ogni sottoclasse

Page 30: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

30

Caratteristiche fondamentali

Astrazione Caratteristiche essenziali di una entità Prima di implementare un oggetto, chiedersi cos’è

e cosa fa’ Incapsulamento

Chiamato anche ‘Information Hiding’ Separazione degli aspetti esterni (accessibili da

oggetti esterni) dalla implementazione interna (nascosti ad oggetti esterni)

Rende i programmi robusti dalle piccole variazioni

Page 31: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

31

Caratteristiche fondamentali Combinazione dei dati e dei comportamenti

Approccio convenzionale: procedurale Gerarchia delle strutture dati Gerarchia delle procedure

OOA ha una gerarchia unificata Gerarchia delle classi

manutenzione più semplice: il codice non deve essere modificato quando viene aggiunta una classe

Importanza del polimorfismo: sposta il problema di decidere l’implementazione da usare alla gerarchia delle classi Esempio: per disegnare in una finestra, basta chiamare un

ipotetico metodo draw. Il metodo corretto viene scelto implicitamente

Page 32: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

32

Vantaggi della programmazione ad oggetti

Protezione delle strutture dati Incapsulamento – information hiding

Maggiore semplicità di progettazione astratta progettazione top-down e bottom-up, gerarchia di classi composizione delle classi come mattoni fondamentali

Migliore riutilizzazione del codice composizione, aggregazione, derivazione

Migliore manutenzione del codice le modifiche sono realizzate mediante aggiunta di classi e

funzioni virtuali – non è necessario riprendere e modificare l’intero codice

Migiore documentazione del codice Strumenti grafici del tipo UML

Page 33: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

33

Modelli orientati agli oggetti

Diagrammi delle classi e delle istanze

Attributi

Persona Giulio:Persona :PersonaCarla : Persona

Giulio:Persona

nome=Giulioeta=24peso=70.1

Carla : Persona

nome=Carlaeta=25peso=??

Persona Nome: stringEtà: integerPeso: float

Page 34: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

34

Modelli orientati agli oggetti

Nei diagrammi delle classi:

Notazione:

Persona NomeIndirizzoLavoro

Cambia_lavoroCambia_indirizzo

File Oggetto geometrico

ColorePosizione

NomeDimensioneData_creazione

print move(vettore delta)Select(point p):booleanRuota(angolo)

Nome della classe

Nome attributo:tipo di dato-1=valore defaultNome attributo:tipo di dato-2=valore default…

Nome operazione-1 (argomenti):tipo risultatoNome operazione-2 (argomenti):tipo risultato…

Page 35: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

35

Modelli orientati agli oggetti Operazioni e metodi

Funzioni o trasformazioni applicate agli oggetti della classe Tutti gli oggetti della classe condividono le stesse operazioni Ogni operazione opera su un oggetto che può essere implicito o

esplicito Un metodo è l’implementazione di una operazione

Esempio: classe File, operazione print, metodi per stampare file ASCII, binari etc.

Polimorfismo: un modo per scegliere il metodo è legato al numero e tipo degli argomenti (sovrapposizione=overloading) Esempio: print(file_name) vs. print(file_pointer)

Polimorfismo: il metodo è scelto sulla base dell’oggetto (aggiramento=overriding)

Page 36: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

36

Inizializza le variabili Ciclo di vita di una variabile locale: nello ‘scope’ in cui e’ definita Ciclo di vita di una variabile dinamica: programma Quando viene generata una variabili di tipo classe, si attiva

automaticamente una funzione che inizializza le variabili della classe: costruttore

Quando la variabile termina il suo ciclo di vita viene attivata automaticamente -se disponibile- una funzione di eliminazione: distruttore (ad esempio delete di variabili nella memoria libera)

Costruttore: funzione con lo stesso nome della classe non richiede tipo di ritorno puo’ avere una lista di argomenti di inizializzazione attivata automaticamente quando si crea un'oggetto con new sono possibili costruttore diversi, che devono avere liste di argomenti

diversi costruttore di default: senza argomenti.

Un primo metodo: il costruttore della classe

Page 37: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

37

Relazioni tra oggetti e classi

Collegamenti e associazioni Associazione: gruppo di collegamenti con struttura comune Vengono lette in una particolare direzione:

I nomi indicano il ruolo di una classe all’interno di una associazione

Si interpreta: Stato - HaCapitale - Città Un collegamento è una istanza di una associazione Tipicamente realizzati mediante puntatori

HaCapitale CapitaleDi

nome nome

Diagramma delle classiStato Città

Page 38: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

38

Relazioni tra oggetti e classi: associazione Molteplicità del ruolo della classe

Descrive quante istanze di una classe possono relazionarsi ad una singola istanza della classe associata Simboli terminatori:

1 uno e solo uno 0..1 zero o uno (opzionale) M..N da M a N * 0 o più (molti) 0..* 0 o più (molti) 1..* 1 o più (molti)

Esempio: punti di intersezione su una linea. Associazione molti-a-molti.

Si interpreta: Linea si relaziona con molti Punti; Punto si relaziona con 2 o più Linee

2..* *Linea Punto

nome nome

Page 39: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

39

Relazioni tra oggetti e classi: associazione

SocietàNomeindirizzo

PersonaNomeIndirizzoCodice fiscaleData di nascita

*

Datorelavoro

impiegato

1 PersonaNomeIndirizzoCodice fiscaleData di nascita

marito

mogliedirigente

dipendente

0..1

0..1

0..1

*

persona casa* cittàpossiede

poligono linea3..*

puntoha lati

Situata in

1..*

*

1..* 0..1

* 2

Page 40: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

40

Esempio di diagramma delle classi

Libro-id+inserisci+rimuovi+cerca

Titolo-nome-autore-isbn-numeroPrenotazioni+inserisci+rimuovi+cerca

Rivista-durataPrestitoPrestito

Data=dataCorrente+inserisci+rimuovi+cerca

ClienteNomeIndirizzoCercaInseriscirimuovi

Prenotazione-Data=dataCorrente+inserisci+rimuovi+cerca

0..*

0..1

0..*

0..*

0..*

Relazioni tra oggetti e classi: associazione n-aria

Page 41: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

41

Relazioni tra oggetti e classi: associazione n-aria

Le associazioni binarie legano due classi. Una classe può legarsi a n classi associazione

n-aria. Simbolo:

Lezioneargomento

+

CorsoData_inizioData_fine

Aula Giorno e ora

Insegnante studenti

1

1 *

1..* 1

Page 42: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

42

Relazioni tra oggetti e classi

Aggregazione: Esprime la forza della associazione o tra classi. Simbolo: Puramente logico Sia il tutto che le parti esistono indipendentemente

Asimmetrico, bidirezionale, transitivo Composizione: più forte della aggregazione.

Simbolo: Le parti esistono solo in relazione al tutto

Persona Persona genitore figlio

*0..2

Automezzo Motore 11

Page 43: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

43

Aggregazione

Avalore : int

A()incrementa()~A()

Bvalore : int

B()incrementa()~B()decrementa()set()val()

0..1 1

-contenuto

0..1 1

• Rappresenta un tipo di contenimento tra classi• Contenimento lasco: B = contenitore, A = contenuto

•Contenimento lasco:• ciclo di vita oggetto contenuto e contenitore indipendenti• il contenitore non è responsabile della creazione e della distruzione dell’oggetto• si realizza mediante un puntatore al contenuto• il coordinatore dell’aggregazione deve:

•Creare oggetto contenuto•Definire e inizializzare un puntatore ad esso•Costruire oggetto contenitore passando puntatore al contenuto

Page 44: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

44

Composizione

1

Avalore : int

A()incrementa()~A()

Bvalore : int

B()incrementa()~B()decrementa()set()val()

1 1

-contenuto

1

• Rappresenta un tipo di contenimento tra classi• Contenimento stretto: B = contenitore, A = contenuto• l’oggetto contenuto non ha una vita propria• l’oggetto contenitore è responsabile della costruzione e distruzione• si realizza con un oggetto contenuto interno al contenitore• è responsabilità del coordinatore

• creare l’oggetto contenitore • fornire valori oggetto contenuto

• il compilatore richiama il costruttore e il distruttore del contenuto

Page 45: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

45

Confronto tra contenimento e derivazione Consideriamo i due casi:

La classe B contiene la classe A (contenimento) La classe B è derivata dalla classe A (ereditarietà) In entrambi i casi l’oggetto B contiene l’oggetto A

Interfacce: Contenimento: l’interfaccia di A e B indipendenti Derivazione: interfaccia di B comprende quella di A

Ereditarietà più forte del contenimento: B può eseguire overriding delle funzioni di A Un puntatore a B può essere assegnato a puntatore a A Un oggetto B può essere assegnato ad un oggetto A

Page 46: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

46

Esempio di aggregazione tra classi

AutomobileMarca : stringaModello : stringaVelocità : floatAccelerazione : floatMuoviAvanti()MuoviIndietro()MarciaSu()Avvia()

CarrozzeriaNumeroSerie : stringaColore : enum […]Peso : float

Motore

NumeroSerie : stringa

Marca : stringa

NumeroValvole : enum[…]

NumeroCilindri : enum[…]

Peso : float

Start : Boolean•Carrozzeria e Motore hanno vita propria!!•Ogni istanza di Automobile ha una

Carrozzeria e un Motore Contenimento LASCO

Page 47: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

47

Associazioni tra classi

Associazione uno-a-uno

Come si realizza? Con un puntatore alla classe associata Ogni classe ha un metodo ‘collegati al partner’ Il coordinatore:

Crea oggetti a e b Collega a con b Collega b con a

A

A()col legaPartner()~A()

B

B()col legaPartner()~B()

associazione

Page 48: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

48

Associazioni tra classi

A

A()col legaPartner()~A()

B

B()col legaPartner()~B()

associazione

Ruolo di A Ruolo di B

• Associazione uno a uno con indicazione dei ruoli

• Associazione uno a molti A

A()col legaPartner()~A()

B

B()col legaPartner()~B()

associazione

*• Ad un oggetto della classe A corrispondono più oggetti della classe B• Ad un oggetto della classe B corrisponde un oggetto di A

• Nella classe A c’è una lista di puntatori alla classe B• lista statica se si conosce il numero massimo di oggetti• altrimenti lista dinamica

Page 49: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

49

Associazioni tra classi Esempio: associazione Persona-Automobile

Automobilemarca : char [10]model lo : char [10]

~Automobi le()Automobile()col legaPi lota()Avvia()

Personanome : char [10]cognome : char [10]eta : int

persona()col legaVetturaPilotata()~Persona()col legaAutomobilePosseduta()col legaComproprietario()

• l’associazione ‘possiede’ ha-Molteplicità 1 a (0..1)

una persona possiede 0 o 1 automobileUna automobile è posseduta da 1 personaDirezionalità: da Persona a Automobile (Automobile non ha traccia della associazione)

possiede

guida

0..1

0..1

pilota vettura

coproprietario

Page 50: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

50

Associazioni tra classi

l’associazione ‘guida’ ha Molteplicità 1 a (0..1)

una persona può guidare 0 oppure 1 automobile Una automobile è guidata da 1 persona Direzionalità: bidirezionale (Automobile e persona hanno

traccia della associazione ‘guida’)

l’associazione ‘coproprietario’ Riflessiva Molteplicità 0..1 a 0..1

Page 51: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

51

Relazioni tra oggetti e classi

Molteplicità (esempi)

=

PersonaPersonaPersona

nomeindirizzo

nomeindirizzo

nomeindirizzo

valutazione

valutazione

coordinatoredipendente

coordinatore

dipendente

Persona

nomeindirizzo

Azienda

nomeindirizzo

Stipendiomansione

File Utente

nomenome

Permessi

Page 52: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

52

Esempio (I)

Dato il seguente diagramma degli oggetti tracciare il corrispondente diagramma delle classi

Punto -1010

Poligono

Punto 10-10

Punto 1010

Punto -10-10

Page 53: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

53

Soluzione esempio (I)

Diagramma delle classi

PoligonoPuntox:coordinatay:coordinata

3..*

(ordinata)

Note: Il più piccolo nr di punti = 3 Associazione ‘ordinata’ = indica che i punti sono

in sequenza

Page 54: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

54

Esempio (II) Diagramma degli oggetti per due triangoli con

un lato in comune Se un punto appartiene ad un solo triangolo

Punto -1,0 Poligono

Punto 1.0

Punto 0,1

Punto -1,0 Poligono

Punto 1.0

Punto 0,-1

Page 55: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

55

Esempio (III) Se un punto appartiene ad uno o più triangoli

Punto -1,0

Poligono Punto 1.0

Punto 0,1

Poligono

Punto 0,-1

Page 56: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

56

Esempio (IV)

Diagramma ad oggetti per descrivere grafi non orientati

Grafo non orientato

Verticenome del vertice

Latonome del lato

2

0..* 0..*

0..*

Page 57: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

57

Esempio (V)

Diagramma ad oggetti per descrivere grafi orientati

Grafo orientato

Verticenome del vertice

Latonome del lato

da

a

0..*

0..*

0..*

0..*

Page 58: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

Linguaggi di programmazione a oggetti C++ (Stroustrup ‘83)

Ispirato principalmente da Simula67

Java1. JDK 1.0 (January 23, 1996)

2. JDK 1.1 (February 19, 1997)

3. J2SE 1.2 (December 8, 1998)

4. J2SE 1.3 (May 8, 2000)

5. J2SE 1.4 (February 6, 2002)

6. J2SE 5.0 (September 30, 2004)

7. Java SE 6 (December 11, 2006)

1. Java SE 6 Update 10

8. Java SE 7

58

Page 59: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

Integrated Developments Environments Eclipse http://download.netbeans.org/netbeans/6.1/

final/ Jbuilder

59

Page 60: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

60

sinonimi (alias) per lo stesso oggetto il tipo dell’oggetto determina il tipo del riferimento puo’ essere visto come un tipo speciale di puntatore deve essere inizializzato e agisce solo su un oggetto uso principale: argomenti e risultati di una funzione

//oop3.cpp #include <iostream.h> main(){ float p; float &rp=p; //rp=riferimento a p (alias di p) p=3.14; rp=6.28; cout << "p =" << p << " rp=" << rp << '\n'; const float &rp1=p; //rp1 e' alias di p, ma l'oggetto riferito e' costante //rp1 non puo' modificare l'oggetto // rp1=3.1; ILLEGALE: non si puo' modificare un oggetto costante! cout << "rp1=" << rp1 <<'\n'; } Output: p =6.28 rp=6.28 rp1=6.28

Riferimenti (specificatore &)

Page 61: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

61

Uso dei riferimenti come argomenti e risultati di funzione senza passare esplicitamente l’indirizzo//opp4.cpp#include <iostream.h>int incrementa(int &val){

val++; if(val>65000) val=65000; return 0;}int incrementa(int &val, int v){

int t=v;

t++; if(t>65000) t=65000; return t;}main(){

int i=7;

cout << " i=" << i; incrementa(i); cout << " i=" << i << " i=" << incrementa(i,i) << " i=" << i << '\n';}Output: i=7 i=8 i=9 i=8

Page 62: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

62

//Altri esempi di alias #include <iostream.h> //oop5.cpp void scambia(int &rx, int &ry) { int t=rx; rx=ry; ry=t; } main() { int x=20; int y=30; cout << "x, y =" << x << ' ' << y; scambia(x,y); cout << "x, y =" << x << ' ' << y; } //oop6.cpp ************************************************************* #include <iostream.h> int &max(int &a, int &b) { if(a>=b) return a; return b; } main() { int x, y; cin >> x >> y; cout << " il massimo tra " << x << " e " << y << "e' " << max(x,y); } Altra versione: int &max(const int &a, const int &b) { if(a>=b) return (int &)a; //il casting e’ necessario per via di const return (int &)b; }

Page 63: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

63

specificatore “inline”: inline void funzione(..) sostituisce il codice della funzione alle chiamate di funzione. : attenzione alla crescita delle dimensioni del codice!

campo di visibilità delle dichiarazioni: identificatori: dalla dichiarazione fino alla fine della funzione identificatori globali sono visibili dalla dichiarazione alla fine del file identificatore locale maschera un identificatore globale con un stesso nome Scope o operatore di visibilità “::” specifica la variabile da utilizzare identificatori locali non sono visibili all'esterno della funzione l’identificatore “::var” identifica la variabile globale blocco: sequenza di istruzioni tra graffe

//opp7.cpp #include <iostream.h> void build(float *val, int size=10) { for(short i=0; i<size; i++) val[i]=(float)i; } main() { float A[100]; int N=10; build(A); //non e' necessario usare build(A,N): viene usato il valore di default for(short i=0; i<10; i++) cout << A[i] << ' '; }

Argomenti di default in una funzione

Page 64: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

64

una funzione e’ un blocco visibilita’ locale: identificatori definiti all’interno di un blocco visibilita’ a livello di file: funzioni e identificatori definiti fuori da tutte le

funzioni visibilita’ degli identificatori di blocchi annidati visibilita’ delle etichette: nel corpo della funzione a cui il blocco appartiene//oop8.cpp #include <iostream.h> int a=1; main() {

int aext=a; int a=2; { int aext=a; int a=3; { int aext=a; int a=4; cout << "exta=" << aext << " interno a=" << a << " ::a=" << ::a << endl; } cout << "aext=" << aext << " esterno a=" << a << " ::a=" << ::a << endl; } cout << "aext=" << aext << " main a=" << a << " ::a=" << ::a << endl; } Output: aext=3 interno a=4 ::a=1 aext=2 esterno a=3 ::a=1 aext=1 main a=2 ::a=1

Page 65: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

65

una classe è il modello-prototipo-al quale si conformano gli oggetti che istanziano la classe

struttura di una classe: class nome_classe{

private:// dati e metodi accessibili solo ai metodi della classe. Sono quindi nascosti all’esterno (non accessibili direttamente)protected:// privati all’esterno; dati e metodi accessibili solo all’interno della classe e tramite classi derivate public:// dati e metodi accessibili pubblicamente a tutte le funzioni dello stesso scope dell’oggetto

}; le componenti funzionali dichiarati in una struttura possono essere definite

all'interno, (inline) o all'esterno una classe introduce un nuovo tipo di dati

Le classi in C++

Page 66: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

66

il tipo di dato definito con le classi, in cui cioè la struttura interna è inaccessibile, e dal quale si possano istanziare oggetti manipolabili solo per mezzo delle operazione associate, è detto “tipo di dato astratto” (ADT)

esempio di tipo di dato astratto “contatore”

class contatore

{

private:

unsigned int valore;

public:

contatore(); //un costruttore

void incrementa();

void decrementa();

void set(unsigned int n);

unsigned int val();

};

l'implementazione della classe può essere realizzato in un file separato o inline

Le classi in C++

Page 67: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

67

Un contatore

contatorevalore : unsigned int

incrementa()contatore()decrementa()set()val()

Page 68: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

68

i metodi vengono attivati inviando all'oggetto un messaggio con il nome del metodo usando l’operatore punto “.”:

c1.incrementa();//invia all’oggetto c1 la richiesta di attivare //incrementa

c1.visualizza();//analogamente Puntatore ad oggetto: operatore freccia a destra “->”:

#include <iostream.h> //per la cout #include "contatore.h" //definizioni e metodi della classe contatore precedente contatore::contatore(){valore=0;}; void contatore::incrementa(){if(valore<65535) valore++;}; void contatore::decrementa(){if(valore>0) valore--;}; void contatore::set(unsigned int n){if((valore>=0)&&(valore<65535)) valore=n;}; unsigned int contatore::val(){return valore;}; void main() { contatore c1; contatore *c3=new contatore; cout << "c1=" << c1.val() << "c3=" << c3->val() << endl;; c1.set(10); c3->set(5); cout << "c3->val()=" << c3->val() << endl; for(short i=0; i<10; i++){ c1.incrementa(); c3->incrementa(); } cout << "valore finale di c1=" << c1.val() << " finale di c3=" << c3->val() ; }

Le classi in C++

Page 69: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

69

invio di dati ad una procedura vs. invio di un messaggio all'oggetto ma: quando un oggetto riceve un messaggio, determina come deve

essere elaborato il dato sottostante usando i metodi associati al dato non posso elaborare direttamente i dati! Es. c1.valore non è

possibile i metodi possono essere definiti anche in più file la classe contatore potrebbe anche essere realizzata con una struttura:

#include <stdio.h>

struct contatore

{

unsigned int valore;

};

main()

{

contatore c1, c2;

c1.valore++;

c2.valore++;

}

ma: in questa forma i dati sono pubblici e la funzione principale accede direttamente al dato sottostante

Le classi in C++

Page 70: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

70

Strutture dati astratte ‘punto’ e ‘stringa’

puntox : inty : int

punto()punto()MuoviPunto()StampaPunto()

stringalen : intstr : char*

stringa()stringa()stampa()

Page 71: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

71

#include <iostream.h> class punto { int x,y; //coordinate private public: punto(){x=0; y=0;}; //costruttore di default punto(int a, int b) {x=a; y=b;}; //altro costruttore (overloading delle funzioni) void MuoviPunto(int d1, int d2) { x+=d1; y+=d2; return; } void StampaPunto(){ cout << "x=" << x <<" y=" << y;} }; main() { punto p1;

punto p2(1,2); //attiva il secondo costruttore

p2.MuoviPunto(1,1); //attiva MuoviPunto

p2.StampaPunto(); }

Le classi in C++Abstract Data Type : classe punto

Page 72: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

72

Costruttori e distruttori delle classi necessità di inizializzare le variabili ciclo di vita di una variabile locale: nello scope in cui e’ definita ciclo di vita di una variabile dinamica: programma quando viene generata una variabili di tipo classe, si attiva

automaticamente una funzione che inizializza le variabili della classe: costruttore: funzione con lo stesso nome della classe

non richiede tipo di ritorno; puo’ avere una lista di argomenti attivata automaticamente quando si crea un'oggetto con new sono possibili costruttore diversi, che devono avere liste di argomenti

diversi costruttore di default: senza argomenti.

quando la variabile termina il suo ciclo di vita viene attivata automaticamente -se disponibile- una funzione di eliminazione: distruttore (ad esempio delete di variabili nella memoria libera)

Costruttore di copia: Quando si passa o si ritorna un oggetto ad una funzione In generale quando si copia un oggetto

Le classi in C++

Page 73: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

73

#include <iostream.h>// Esempio di costruttori per copiaclass stringa{

int len; char *ch; public: stringa() {cout << "costruttore di default" << endl; len=0;}//costruttore di default stringa(const char *s) //costruttore con argomenti; s e' puntatore a stringa costante

{ cout << "costr. con argomenti" << endl; len=strlen(s); ch=new char[len+1]; strcpy(ch,s);}

stringa(const stringa&s) //costruttore di copia { cout << "costruttore di copia" << endl; len=s.len; ch=s.ch;}

void list(){cout<<ch<<endl;} int val(){return len;} void set(int n){len=n;}

void setp(char *ps){ch=ps;}};int lung(stringa s){return s.val();} //usa l'inizializzazione di copiastringa crea(int l){ stringa s; char *ps; s.set(l); ps=new char[l+1]; s.setp(ps); return s;} //usa l’iniz. di copia}main(){

stringa a; //costruttore di default stringa b("Luigi"); //costruttore con argomenti stringa c=b; //costruttore di copia c.list(); cout << lung(c); a=crea(10); cout << lung(a);}

Output:costruttore di default Costr. con argomenti costruttore di copiaLuigi costruttore di copia 5costruttore di default costruttore di copia costruttore di copia10

Page 74: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

74

Un numero complesso

complessopr : floatpi : float

complesso()complesso()add()sub()mpy()visualizza()

Page 75: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

75

numeri complessi

//#include <stdio.h>#include <iostream.h>#include <stdlib.h>#include <string.h>class complesso{

private: float pr, pi;

public: complesso(){pr=0;pi=0;} //costruttore di default complesso(float x,float y); //altro costruttore void cadd(complesso arg); //operazione binaria void csub(complesso arg); //operazione binaria

void cmult(complesso arg);void visualizza();

};// definizione funzionicomplesso::complesso(float x, float y){ pr=x; pi=y; }void complesso::cadd(complesso arg){ pr+=arg.pr; pi+=arg.pi; }void complesso::csub(complesso arg){ pr-=arg.pr; pi-=arg.pi; }void complesso::cmult(complesso arg){ float temp1, temp2;

temp1=pr*arg.pr - pi*arg.pi; temp2=pr*arg.pi + pi*arg.pr; pr=temp1; pi=temp2; }

Page 76: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

76

void complesso::visualizza(){

if(pi<0)cout << '\n' << "complesso: " << pr << "- j" << abs(pi);

elsecout << '\n' << "complesso: " << pr << "+ j" << pi;

}main(){

complesso a(1,3), b(2,2); complesso *c; c=new(complesso(3.14,1.2)); a.visualizza(); b.visualizza();

c->visualizza(); a.cadd(b); b.cadd(b); a.visualizza(); b.visualizza(); a.csub(b); a.visualizza(); b.visualizza(); a.cmult(b); a.visualizza(); b.visualizza();}

Output:complesso: 1+ j3complesso: 2+ j2complesso: 3+ j5complesso: 4+ j4complesso: -1+ j1complesso: 4+ j4complesso: -8+ j0complesso: 4+ j4

Page 77: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

77

ADT nodo ADT lista

nodovalore : int

nodo()loadn()loadv()getn()getv()

1

0..1

-next

lista

l ista()~lista()insert()add()hremove()tremove()type()

0..1

1

-head

1

0..1

0..1

1

Page 78: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

78

//esempio di ADT nodo ADT lista#include <stdio.h>#include <iostream.h>#include <stdlib.h>#include <string.h>

class nodo{

private: nodo *next;

int valore; public: nodo(){next=NULL;} void loadn(nodo *a){next=a;} void loadv(int a){valore=a;} nodo *getn(){return next;} int getv(){return valore;}};class lista{

private: nodo *head; public:

lista(){head=NULL;} //costruttore~lista(){} //distruttore: lasciato per esercizio!

void insert(int n); //at the top void add(int n); //at the bottom int hremove(); //toglie dalla cima int tremove(); //toglie dalla coda void type(); //visita dalla cima e stampa il contenuto};

Page 79: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

79

void lista::insert(int n){

nodo *temp;

temp=new nodo; temp -> loadv(n); temp -> loadn(NULL); if(head) {temp -> loadn(head); head=temp;} else {temp -> loadn(NULL); head=temp;}}

void lista::add(int n){

nodo *temp, *prec;

if(head){ temp=head; while(temp){ prec=temp; temp=temp->getn(); } prec->loadn(new nodo); prec=prec->getn(); prec->loadv(n); prec->loadn(NULL); } else { head=new nodo; head -> loadv(n); head -> loadn(NULL); }}

Page 80: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

80

int lista::hremove()

{

int n;

if(head){

n=head->getv();

head=head->getn();

return(n);

} else return(65536); //65536 means empty

}

int lista::tremove()

{

int n;

nodo *temp, *prec;

temp=head;

if(head){

while(temp->getn()) {

prec=temp;

temp=temp->getn();

}

n=temp->getv(); prec->loadn(NULL);

delete(temp);

return(n);

} else return(65536); //65536 means empty

}

Page 81: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

81

void lista::type()

{

nodo *temp;

temp=head;

while(temp){

cout << temp->getv() << '\n';

temp=temp->getn();

}

}

main()

{

lista L1, L2;

int n;

for(int i=0; i<5; i++) L1.insert(i);

cout << "L1:" << '\n'; L1.type();

L2.add(10); L2.add(100);

cout << "L2:" << '\n'; L2.type();

L1.add(5); L1.add(6); L1.add(7);

cout << "L1 after add" << '\n';

L1.type();

cout << "L1hrem " << L1.hremove() << '\n';

cout << "L1hrem " << L1.hremove() << '\n';

while( (n=L2.tremove())!=65536) cout << "L2 trem " << n << '\n';

while( (n=L1.hremove())!=65536) cout << "L1 hrem " << n << '\n';

}

Page 82: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

82

Autoriferimento nelle classi: l'argomento implicito 'this‘ una classe può contenere oggetti di altre classi, puntatori a oggetti di altre classi, puntatori a

oggetti della stessa classe (autoriferimento) ogni oggetto contiene un puntatore, chiamato this, che contiene l'indirizzo dell'oggetto stesso Nota: ogni oggetto contiene al proprio interno le variabili definite nella classe, ma non i

metodi: ci possono essere molte istanze di una classe ma una sola istanza delle funzioni il puntatore all'oggetto ‘this’ viene passato implicitamente alle funzioni della classe al

momento della loro attivazione, per sapere qual è l'oggetto attivatore

 #include <iostream.h> class contatore { unsigned int valore; //privato! // contatore *const this; questa definizione e' creata implicitamente public: contatore(); void inc(); void dec(); void set(unsigned int n); unsigned int val(); }; contatore::contatore(){this->valore=0;}; void contatore::inc(){if(this->valore<65535) this->valore++;}; void contatore::dec(){if(this->valore>0) this->valore--;}; void contatore::set(unsigned int n){ this ->valore=n;}; unsigned int contatore::val(){return this->valore;}; main() { //invariato contatore c1,c2; c2.set(10); for(short i=0; i<10; i++){ c1.inc(); c2.inc(); } cout << "valore finale di c1=" << c1.val() << " finale di c2=" << c2.val(); }

Le classi in C++

Page 83: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

83

Le classi in C++

Esempio di autoriferimento: concatenazione di stringhe

#include <iostream.h>

class stringa{

int len; //dati privatichar *str;

public: //definizione dei metodistringa(int=0);stringa(const char *);stringa &concat(const stringa&);char *visualizza();

};//in questo modo è possibile scrivere:main(){

stringa a(80);stringa b("sequenza");stringa c(" di questa");stringa d(" prova");

 a=b.concat(c).concat(d);cout << a.visualizza();

}

Page 84: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

84

//implementazione dei metodistringa::stringa(int n){ len=n; if(n>0){ str=new char (len+1); str[0]='\0'; } }

stringa::stringa(const char *s){ len=strlen(s); str=new char[len+1]; strcpy(str,s); }

char* stringa::visualizza(){ return str; }

stringa& stringa::concat(const stringa &s){

len += s.len;char *temp=new char[len+1];strcpy(temp,str);strcat(temp, s.str); //temp="sequenza di questa"str=temp; //str e' la stringa dell'oggetto che ha attivato concatreturn *this; //ritorna l'oggetto che ha attivato concat

} Output:sequenza di questa prova

Page 85: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

85

Overloading degli operatori  ridefinizione di simboli del linguaggio notazione infissa anche fra tipi diversi limiti:

solo operatori gia’ definiti l’operatore che viene ridefinito conserva le sue caratteristiche di associativita’, precedenza e

numero di argomenti almeno uno degli argomenti deve essere di tipo classe non si possono usare operatori che non hanno significato in C (es. **)

Specificatore: operator <operatore da sovrapporre> operatore binario: definito da un metodo interno con un argomento - a.add(b) – oppure

con due argomenti – a=a.add(a,b) - classe C { priv; ... public: C binary_op(C); C binary_op(C, C); } classe binary_op(classe arg){return classe(priv+arg.priv);}

classe binary_op(classe arg1, classe arg2){ return classe(arg1.priv+arg2.priv);} main(){

a.binary_op(b);a=a.binary_op(a,b);

}

Le classi in C++

Page 86: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

86

Operatori del C++ che possono essere sovrapposti:

+ - * / % ^ & | ~!

= < > += -= *= /= %= ^=&=

|= << >> >>= <<= == != <= >=&&

|| ++ -- [] () new delete

Le classi in C++

Page 87: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

87

operatore unario: metodo intero ad una classe senza argomenti operatore unario U: l'espressione argomento U oppure U argomento può essere:

argomento.U() oppure U(argomento)

non è possibile realizzare applicazione prefissa e postfissa

/* Uso degli operatori unari e binari */

//

#include <iostream.h>

void main()

{

int a=1;

int b;

cout << "prima a= " << a << '\n';

b = a++; // l'operatore post-incremento e' unario: prima assegna e poi incrementa

cout << "dopo a++: a= " << a << " b=" << b <<'\n';

a=1;

b = ++a; /* l'operatore pre-incremento e' unario: prima incrementa e poi assegna*/

cout << "dopo ++a: a= " << a << " b=" << b <<'\n';

a=1;

b = a+1; /* l'operatore somma e' binario: prima somma e poi assegna */

cout << "dopo a+1: a= " << a << " b=" << b <<'\n';

}

Le classi in C++

Page 88: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

88

Sovrapposizione degli operatori: esempio

contatorevalore : unsigned int

contatore()operator ++()operator --()operator ()()val()

Page 89: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

89

overloading di operatori unari#include <iostream.h>//class contatore{

unsigned int valore; public: contatore(){valore=0;} void operator++(){if(valore<65535) valore++;}//overloading di ++ void operator--(){if(valore>0) valore--;}//overloading di () void operator()(unsigned int n){if((valore>=0)&&(valore<65535)) valore=n;} unsigned int val(){return valore;}};

main(){

contatore c1,c2;c2(10);

for(short i=0; i<10; i++){ c1++; c2++; } cout << "valore finale di c1=" << c1.val() << " finale di c2=" << c2.val();}

Output:Valore finale di c1=10 finale di c2=20

Sovrapposizione degli operatori: esempio

Page 90: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

90

Sovrapposizione operatori e numeri complessi

//#include <stdio.h>#include <iostream.h>#include <stdlib.h>#include <string.h>class complesso{

private: float pr, pi;

public: complesso(){pr=0;pi=0;} //costruttore di default complesso(float x,float y); //altro costruttore void cadd(complesso arg); //operazione binaria void csub(complesso arg); //operazione binaria

void cmult(complesso arg);void visualizza();

};// definizione funzionicomplesso::complesso(float x, float y){ pr=x; pi=y; }void complesso::cadd(complesso arg){ pr+=arg.pr; pi+=arg.pi; }void complesso::csub(complesso arg){ pr-=arg.pr; pi-=arg.pi; }void complesso::cmult(complesso arg){ float temp1, temp2;

temp1=pr*arg.pr - pi*arg.pi; temp2=pr*arg.pi + pi*arg.pr; pr=temp1; pi=temp2; }

Page 91: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

91

void complesso::visualizza(){

if(pi<0)cout << '\n' << "complesso: " << pr << "- j" << abs(pi);

elsecout << '\n' << "complesso: " << pr << "+ j" << pi;

}main(){

complesso a(1,3), b(2,2); a.visualizza(); b.visualizza();

a.cadd(b); b.cadd(b); a.visualizza(); b.visualizza(); a.csub(b); a.visualizza(); b.visualizza(); a.cmult(b); a.visualizza(); b.visualizza();}

Output:complesso: 1+ j3complesso: 2+ j2complesso: 3+ j5complesso: 4+ j4complesso: -1+ j1complesso: 4+ j4complesso: -8+ j0complesso: 4+ j4

Page 92: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

92

Overloading operatori e numeri complessi: seconda versione

//#include <iostream.h>#include <math.h>class complesso{

private: float pr, pi; public: complesso(){pr=0;pi=0;} //costruttore di default complesso(float x,float y); //altro costruttore complesso cadd(complesso arg); complesso csub(complesso arg);

complesso cmult(complesso arg);void visualizza();

};complesso::complesso(float x, float y){ pr=x; pi=y; }complesso complesso::cadd(complesso arg){complesso t; t.pr=pr+arg.pr; t.pi=pi+arg.pi;

return t;}complesso complesso::csub(complesso arg){complesso t; t.pr=pr-arg.pr; t.pi=pi-arg.pi;

return t;}complesso complesso::cmult(complesso arg) { complesso t; float temp1, temp2;

temp1=pr*arg.pr - pi*arg.pi; temp2=pr*arg.pi + pi*arg.pr; t.pr=temp1; t.pi=temp2; return t;

}

Page 93: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

93

void complesso::visualizza()

{

if(pi<0)

cout << '\n' << "complesso: " << pr << "- j" << abs(pi);

else

cout << '\n' << "complesso: " << pr << "+ j" << pi;

}

main()

{

complesso a(1,3), b(2,2); a.visualizza(); b.visualizza();

a=a.cadd(b); b=b.cadd(b); a.visualizza(); b.visualizza();

a=a.csub(b); a.visualizza(); b.visualizza();

a=a.cmult(b); a.visualizza(); b.visualizza();

}

Page 94: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

94

overloading degli operatori e numeri complessi

//#include <stdio.h>#include <iostream.h>#include <stdlib.h>#include <string.h>class complesso{

private: float pr, pi; public: complesso(){pr=0;pi=0;} //costruttore di default complesso(float x,float y); //altro costruttore complesso operator+(complesso arg); complesso operator-(complesso arg);

complesso operator*(complesso arg);complesso operator*(float arg);void visualizza();

};// definizione funzionicomplesso::complesso(float x, float y){ pr=x; pi=y; }complesso complesso::operator+(complesso arg) //complesso operator+(complesso b)

{{ complesso t; t.pr=pr+arg.pr; t.pi=pi+arg.pi; return t;}complesso complesso::operator-(complesso arg){ complesso t; t.pr=pr-arg.pr; t.pi=pi-arg.pi; return t;}

Page 95: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

95

complesso complesso::operator*(complesso arg){ complesso t; float temp1, temp2;

temp1=pr*arg.pr - pi*arg.pi; temp2=pr*arg.pi + pi*arg.pr; t.pr=temp1; t.pi=temp2; return t;

}complesso complesso::operator*(float arg){ //prodotto con tipo diverso!

return complesso(arg*pr, arg*pi);}void complesso::visualizza(){

if(pi<0)cout << '\n' << "complesso: " << pr << "- j" << abs(pi);

elsecout << '\n' << "complesso: " << pr << "+ j" << pi;

}main(){

complesso a(1,3), b(2,2), c, d; a.visualizza(); b.visualizza();

a=a+b; b=b+b; a.visualizza(); b.visualizza(); a=a-b; a.visualizza(); b.visualizza(); a=a*b; a.visualizza(); b.visualizza();

a=a*2; //attenzione: non e’ possibile 2*a!a.visualizza(); c=a+a; a=((a+b-c)*c)*2; a.visualizza();

}

Page 96: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

96

La classe A può dichiarare ‘amica’ la classe B

Auno : intdue : inttre : int

A()inc()lst()

Buno : intdue : int

B()lst()dec()

Page 97: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

97

Relazioni tra oggetti e classi: generalizzazione/specializzazion

eMammiferi

Cani Gatti

Page 98: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

98

Relazioni tra oggetti e classi: generalizzazione/specializzazion

e Introducono una gerarchia di classe Generalizzazione: una superclasse fattorizza le proprietà

comuni di un insieme di classi Generalizzazione: asimmetrica, non riflessiva, transitiva Simbolo:

superclasse

subclasse

Classe più generaleClasse meno generale

Generalizzazione

Specializzazione

classipiùgenerali

classipiùspecializzate

Page 99: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

99

Relazioni tra oggetti e classi: generalizzazione/specializzazion

e

Figura

posizione

colore

display

Segmento

Coordinate

display

Rettangolo

Vertici

display

Arco

raggio

angolo iniziale

ancolo finale

display

Figura

posizione

colore

display

Segmento

Coordinate

display

Rettangolo

Vertici

display

Arco

raggio

angolo iniziale

ancolo finale

display

=

Attributi, operazioni e relazioni della superclasse vengono ereditate dalle sottoclassi se protetti

Page 100: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

100

Top-down:

Bottom-up:

Classe base(componente complesso)

Sottoclassi (componenti minime)

Automobile

ruota carrozzeria motore

Classe base(componente minimo)

Sottoclassi (componenti via via piu’ complesse)

veicolo

Veicolo senza motore

Veicolo a motore

moto auto

taxi

aereo

Relazioni tra oggetti e classi: generalizzazione/specializzazion

e

Page 101: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

101

Relazioni tra oggetti e classi: generalizzazione/specializzazion

e Ereditarietà multipla

Veicolo

Veicolo a vento

Veicolo a motore

Veicolodi terra

Veicolod’acqua

Camion Barca a vela

Page 102: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

102

Costruttori/distruttore nelle classi derivate legato alla visibilità tra oggetti derivati e oggetti base se un oggetto di classe derivata viene inizializzato, il costruttore deve assicurarsi

che venga eseguita una inizializzazione anche dell'oggetto della classe di base-interna alla classe derivata-.

il costruttore della classe derivata attiva uno dei costruttore della classe base: class Base{

int a;protected:

int bb;public:

int b;void Base(){a=0;}

}class Derivata:public Base{

int c;public: Derivata():Base(){c=0;}int funz(){c=c+bb+b+d; return c;}

}class Derivata2: public Derivata(){... public: derivata2():

Derivata()} 

Le classi in C++

Page 103: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

103

Derivazione (I)

Studente

anno : intf acolta : char*

Studente()presentati()

Persona

eta : intnome : char*

Persona()presentati()

Page 104: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

104

Derivazione (II)

complessopr : floatpi : float

complesso()complesso()add()sub()mpy()visualizza()

compmodulo : floatfase : float

comp()visualizza()c2t()t2c()mult()div()

Page 105: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

105

//ESEMPIO DI CLASSE BASE//file complesso.hclass complesso {

protected: float pr, pi; public: complesso(){pr=0;pi=0;} //costruttore di default complesso(float x,float y); //altro costruttore

void add(complesso arg); void sub(complesso arg);

void mpy(complesso arg);void visualizza();

};

// definizione funzionicomplesso::complesso(float x, float y){ pr=x; pi=y; }void complesso::add(complesso arg) //complesso operator+(complesso b){ co{ pr=pr+arg.pr; pi=pi+arg.pi; }void complesso::sub(complesso arg){ pr=pr-arg.pr; pi=pi-arg.pi; }void complesso::mpy(complesso arg){

float temp1, temp2;temp1=pr*arg.pr - pi*arg.pi; temp2=pr*arg.pi + pi*arg.pr; pr=temp1; pi=temp2;

}void complesso::visualizza(){ if(pi<0) cout << '\n' << "pr,pi " << pr << "- j" << abs(pi); else cout << '\n' << "pr,pi " << pr << "+ j" << pi; }

Page 106: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

106

#include <iostream.h>#include <stdlib.h>#include <math.h>#include "complesso.h"class comp:public complesso{

private: float modulo; //valori trigonometrici float fase; public: comp(float x, float y):complesso(x, y) //costruttore { modulo=sqrt(x*x+y*y); fase=atan(y/x); }

void c2t() { float x=pr; float y=pi; modulo=sqrt(x*x+y*y); fase=atan(y/x); }

void t2c() { pr=modulo*cos(fase); pi=modulo*sin(fase); } void mult(comp arg) { modulo=modulo*arg.modulo; fase=fase+arg.fase; }

void div(comp arg) { modulo=modulo/arg.modulo; fase=fase-arg.fase; } void visualizza() { complesso::visualizza(); cout << " modulo=" << modulo << " fase=" << fase;}};main(){

comp a(1,1); comp b(1,2); a.visualizza(); b.visualizza(); a.mult(b); a.t2c(); a.visualizza(); a.div(b); a.t2c(); a.visualizza();}

Page 107: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

107

////derivazione#include <stdio.h>#include <iostream.h>#include <stdlib.h>#include <string.h>

class complesso{

protected: float pr, pi; public: complesso(float x,float y); //altro costruttore complesso cadd(complesso arg); complesso csub(complesso arg);

void visualizza();};// definizione funzionicomplesso::complesso(float x, float y){

pr=x; pi=y;}

complesso complesso::cadd(complesso arg){

pr+=arg.pr; pi+=arg.pi;}

Page 108: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

108

complesso complesso::csub(complesso arg){

pr-=arg.pr; pi-=arg.pi;}

void complesso::visualizza(){

cout << '\n' << "complesso: " << pr << "+ j" << pi;}

class comp: public complesso //derivazione per estendere la classe{

public: comp(float x, float y):complesso(x, y){};//costruttore comp cmult(comp arg); comp cdiv(comp arg); void visualizza(char a);};//comp comp::cmult(comp arg){

float temp1, temp2;

temp1=pr*arg.pr - pi*arg.pi; temp2=pr*arg.pi + pi*arg.pr; pr=temp1; pi=temp2;}

Page 109: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

109

comp comp::cdiv(comp arg){

float temp, temp1, temp2;

temp=arg.pr*arg.pr + arg.pi*arg.pi; temp1 = (pr*arg.pr + pi*arg.pi)/temp; temp2 = (pr*arg.pi - pi*arg.pr)/temp; pr=temp1; pi=temp2;}void comp::visualizza(char a){

cout << '\n' << a; complesso::visualizza();}

main(){

comp a(1,2), b(2,2); a.complesso::visualizza(); b.complesso::visualizza();

a.cadd(b); b.cadd(b); a.visualizza('a'); b.visualizza('b'); a.csub(b); a.visualizza('a'); b.visualizza('b'); a.cmult(b); a.visualizza('a'); b.cdiv(b); b.visualizza('b');}

Page 110: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

110

Derivazione (III)nodo

valore : int

nodo()loadpun()getpun()loadval()getval()

1

0..1

#next

nodo_extnome : char*flag : int

nodo_ext()nodo_ext()loadnome()getnome()loadflag()getflag()

lista

l ista()add()tremove()type()

0..1

1

-head

1

0..1

0..1

1

Page 111: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

111

// liste derivate#include <stdio.h>#include <iostream.h>#include <stdlib.h>#include <string.h>#include <alloc.h>class nodo{

protected: nodo *next;

int valore; public: nodo(){next=NULL;valore=0;} void loadpun(nodo *a){next=a;} nodo *getpun(){return next;} void loadval(int a){valore=a;} int getval(){return valore;}};class nodo_ext: public nodo{ protected:

char *nome; int flag; public: nodo_ext(char *n, int f):nodo(){strcpy(nome,n);flag=f;} nodo_ext():nodo(){flag=0;nome="";} void loadnome(char *n){nome=new char[strlen(n)+1]; strcpy(nome,n);} char *getnome(){return nome;} void loadflag(int a){flag=a;} int getflag(){return flag;}};

Page 112: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

112

class lista{

private: nodo_ext *head; public:

lista(){head=NULL;} //costruttore void add(int val, char *n, int f); //at the bottom int tremove(); //toglie dalla coda e restituisce il nome void type(); //visita dalla cima e stampa il contenuto};void lista::add(int val, char *n, int f){

nodo_ext *temp, *prec;

if(head){ temp=head; while(temp){ prec=temp; temp=(nodo_ext *)temp->getpun(); } prec->loadpun(new nodo_ext); prec=(nodo_ext*)prec->getpun(); prec->loadval(val); prec->loadflag(f); prec->loadnome(n); prec->loadpun(NULL); } else { head=new nodo_ext; head -> loadval(val);

head -> loadflag(f); head -> loadnome(n); head -> loadpun(NULL); }}

Page 113: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

113

int lista::tremove(){

int n; nodo_ext *temp, *prec; temp=head;

if(head){ while(temp->getpun()) { prec=temp; yemp=(nodo_ext*)temp->getpun(); } n=temp->getval(); prec->loadpun(NULL); delete(temp);

return(n); } else return(65536); //65536 means empty}

void lista::type(){ nodo_ext *temp;

temp=head; while(temp){ cout << "val=" << temp->getval() << " nome=" << temp->getnome() << " flag="

cout << temp->getflag() << '\n'; temp=(nodo_ext*)temp->getpun(); }}main(){ lista L1, L2; int n;

for(int i=0;i<5;i++) L1.add(i,"primo",0); L1.type();

cout << "inizio a rimuovere dalla coda" << '\n'; while((n=L1.tremove())!=65536) cout << "remove L1 " << n << '\n';}

Page 114: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

114

Derivazione (IV)

Personaeta : intnome : char*

Persona()presentati ()

Studenteanno : intfacolta : char*

Studente()presentati ()

Lavoratoreimpresa : intstipendio : float

Lavoratore()presentati ()

Stud_Lavcorso_serale : int

Stud_Lav()presentati ()

Derivazione multipla

Page 115: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

115

Classe base (superclasse) classe derivata (sottoclasse)

Ricerca di una componente interna ad una variabile di sottoclasse: Prima nella sottoclasse - Poi nelle componenti ereditate

Funzioni ridefinite nella sottoclasse:nasconde la funzione della superclasse

Tutte le funzioni sono ancora attive! Si possono chiamare o con casting –

((superclasse) oggetto sottoclasse).funzione – o con Oggetto_sottoclasse.superclasse::funzione

Riprendiamo la classe Studente. l’abbinamento funzione-oggetto e’ fatto STATICAMENTE dal compilatore (all’atto della compilazione) sulla base di tipo oggetto e argomenti

Ma: con i puntatori?

Regole di visibilita’

Page 116: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

116

Puntatori:Studente *giorgio; Persona *giulio;

giorgio=new Studente(“Giorgio Bianchi", "ingegneria", 23,4);

giorgio -> presentati();

Attenzione: i puntatori possono puntare a oggetti diversi! giorgio -> presentati();

giulio=giorgio; giulio->presentati(); // la associazione e’ fatta sulla base del

// tipo del puntatore e non dell’oggetto!!

giulio e’ una persona ma punta ad uno studente!

delete giulio cancella solo la persona: spreco spazio Funzioni virtuali: associazione sulla base del tipo di oggetto

Regole di visibilita’

Page 117: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

117

//oop45.cpp

#include <iostream.h>

class Persona

{

protected:

int eta;

char *nome;

public:

Persona(const char *n, int e){ nome=new char[strlen(n)+1]; strcpy(nome,n); eta=e;}

virtual void presentati()

{

cout << "sono una persona, mi chiamo " << nome << " ed ho " << eta << " anni“

<< endl;

}

};

class Studente:public Persona

{

private:

int anno;

char *facolta;

public:

Studente(char *n, char *f, int e, int a):Persona(n,e)

{ facolta=new char[strlen(f)+1]; strcpy(facolta,f); anno=a; }

virtual void presentati(){

cout<<"sono uno studente di nome "<<nome<<" ho "<<eta<<" anni e sono iscritto a "<<facolta<<" al "<<anno<<" anno di corso" << endl;

}

};

Page 118: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

118

main(){

Persona mario("Mario Verdi", 22); Studente luigi("Luigi Rossi", "ingegneria", 24, 5);

mario.presentati(); luigi.presentati();

Studente *giorgio; Persona *giulio; giorgio=new Studente("Giorgio Bianchi", "ingegneria", 23,4); giorgio -> presentati();

giulio=giorgio; giulio->presentati();}

Output con funzioni virtuali:sono una persona, mi chiamo Mario Verdi ed ho 22 annisono uno studente di nome Luigi Rossi ho 24 anni e sono iscritto a ingegneria al 5 anno di corsosono uno studente di nome Giorgio Bianchi ho 23 anni e sono iscritto a ingegneria al 4 anno di corsosono uno studente di nome Giorgio Bianchi ho 23 anni e sono iscritto a ingegneria al 4 anno di corsOutput o

Output senza funzioni virtualisono una persona, mi chiamo Mario Verdi ed ho 22annisono uno studente di nome Luigi Rossi ho 24 anni e sono iscritto a ingegneria al 5 anno di corsosono uno studente di nome Giorgio Bianchi ho 23 anni e sono iscritto a ingegneria al 4 anno di corsosono una persona, mi chiamo Giorgio Bianchi ed ho 23anni

Page 119: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

119

Polimorfismo e funzioni virtuali Polimorfismo: capacità di rispondere in modo differenziato agli stessi

comandi

realizzato con overloading delle funzioni e con le funzioni virtuali overloading delle funzioni: la scelta della funzione da attivare è effettuata

esaminando una lista degli operandi o il tipo di oggetti tramite cui vengono operate le richieste alle operazioni

abbinamento statico(static binding): deciso alla compilazione abbinamento dinamico(dynamic binding): deciso in run-time

overloading quando gli oggetti vengono rappresentati con puntatore: i puntatori possono puntare a oggetti di tipo diverso! ma l'abbinamento statico si basa sul tipo di puntatore e non sul tipo di

oggetto puntato! funzione virtuale: funzione il cui abbinamento con l'oggetto è fatto in run-

time

sintassi: virtual int funz(){..........} 

Le classi in C++

Page 120: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

120

una funzione definita virtuale nella classe base in una gerarchia di derivazione, rende virtuali tutte le funzioni con stesso prototipo e componenti la classe derivata

 l'abbinamento dinamico oggetto-funzione con le funzioni virtuali funziona solo se gli oggetti sono gestiti con puntatore. Se l'oggetto gestito con il nome, l'associazione e' statica.

tre casi in cui la chiamata di una funzione virtuale è risolta staticamente: quando la chiamata e’ effettuata con un oggetto e non con un

puntatore quando si usa scope (::) alla classe nella chiamata con puntatore quando una funzione virtuale è chiamata all'interno di costruttore

o distruttore  costruttori e distruttori virtuali

Un costruttore non puo’ essere mai dichiarato virtuale (deve essere dichiarato prima)

Distruttori possono essere virtuali!

Le classi in C++

Page 121: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

121

Vantaggi del polimorfismo

Permette di scrivere codice generico che si adatta automaticamente alle specializzazioni future

Permette di creare nuovi metodi senza cambiare il resto del codice Semplice estensione del codice pre-esistente riutilizzabilita’ del codice Attenzione: se l’impostazione e’ corretta, si puo’ cambiare molto lavorando

poco… …se si modifica troppo il codice originale, l’impostazione e’ sbagliata! Modifiche concentrate migliore manutenzione Attenzione: i vantaggi si pagano con una certa perdita di efficienza!

Page 122: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

122

#include <iostream.h>class SuperficiePiana{ protected: float dim1; public: SuperficiePiana(float d) {dim1=d;} virtual void presentati() { cout << “Sono una superficie piana, la mia prima dimensione e' " << dim1 ; } virtual float Area(){ return 0;}};class triangolo: public SuperficiePiana{ private: float dim2; public: triangolo(float d1, float d2) : SuperficiePiana(d1) { dim2=d2; } virtual void presentati() { cout<<“Sono un triangolo di dimensioni " << dim1 <<" e " << dim2 ; } virtual float Area(){ return dim1*dim2/2.; }};class cerchio: public SuperficiePiana{ public: cerchio(float d1):SuperficiePiana(d1) {} virtual void presentati() { cout<< “Sono un cerchio" ; } virtual float Area(){ return 3.14 * dim1*dim1; }};

Page 123: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

123

main(){

SuperficiePiana * f1;

f1=new SuperficiePiana(2.); f1->presentati(); cout << ". La mia area = " << f1->Area() << endl;

f1=new triangolo(2.,4.); f1->presentati(); cout << ". La mia area = " << f1->Area() << endl;

}

//============================================================================// aggiunta della classe trapezioclass trapezio:public SuperficiePiana{ private: float dim2; float dim3; public: trapezio(float d1, float d2, float d3):SuperficiePiana(d1) {dim2=d2;dim3=d3;} void presentati() { cout << "sono un trapezio con basi=" << dim1 << ", " << dim2 <<

" e altezza= " << dim3 ; } float Area(){return (dim1+dim2)*dim3/2; }};

Page 124: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

124

Una classe (ADT):class casa{ ... };

Un oggetto e’ una istanza della classe: casa a; Piu’ oggetti hanno diversi valori delle variabili e stesso comportamento Piu’ oggetti hanno diverse variabili, il codice e’ rientrante:

casa a, mia, tua;

mia.metodo1; //attiva metodo1 mediante l’invio dell’indirizzo di mia al codice di metodo1 Comunicazione tra oggetti tramite invio di messaggi di attivazione

Campo variabiliMetodo1Metodo2Metodo3

privato

pubblico

ogg.a ogg. mia ogg. tua

Codice dei metodi

Puntatore ‘this’Puntatore ‘this’

Ricapitolando …

Page 125: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

125

Comunicazione tra oggetti

Campo variabiliMetodo1Metodo2Metodo3 Campo variabili

Metodo1Metodo2Metodo3

Campo variabiliMetodo1Metodo2Metodo3

a

tua

mia

Chiama tua.metodo2

Chiama mia.metodo1

Ricapitolando …

Page 126: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

126

Terminologia: Classe derivata: classe ottenuta mediante specializzazione di un’altra

classe Classe base: la classe dalla quale una classe è derivata Ereditarietà: una classe derivata eredita da una classe base

Ereditarietà impropria: quando la classe base ha una capacità che la classe derivata non può soddisfare (esempio: nella derivazione struzzo:uccello la classe base ha un metodo vola())

Costruttori/distruttori: inizializzazione var-rilascio spazio Istanziazione oggetto/terminazione oggetto nome uguale alla classe, senza return parametri opzionali, possibili costruttori multipli Costruttore di default / di copia Attenzione: l’inizializzazione del costruttore segue l’ordine di definizione variabili

Ricapitolando …

Page 127: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

127

Ereditarietà Relazione has-a (composizione) Relazione is-a (specializzazione/derivazione)

Esempio: Se il problema si descrive con la frase: …un veicolo contiene una o più

ruote… Implementare la classe ‘ruota’ e poi la classe ‘veicolo’:

class veicolo{ private: Ruota r1,r2,r3;}

Se si descrive con la frase: …un’auto è un veicolo… Implementare la classe ‘veicolo’ e poi la classe ‘auto’:

class auto:public veicolo{ private: ...

} auto *a=new auto(); veicolo *v=new veicolo(); v=a; //lecito a=v; //errato

Ricapitolando …

Page 128: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

128

Array di oggetti: il costruttore e il distruttore vengono chiamati per ciascun elemento dell'array per un vettore di oggetti appartenenti ad una classe con un costruttore, la

classe deve avere un costruttore senza argomenti Costruttori/distruttore nelle classi derivate

legato alla visibilità tra oggetti derivati e oggetti base se un oggetto di classe derivata viene inizializzato, il costruttore deve

assicurarsi che venga eseguita una inizializzazione anche dell'oggetto della classe di base-interna alla classe derivata-.

il costruttore della classe derivata attiva uno dei costruttore della classe base

Ricapitolando …

Page 129: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

129

Polimorfismo: Capacità degli oggetti di differenti classi legate da ereditarietà

di rispondere differentemente alla stessa chiamata Ottenuto mediante overloading delle funzioni e funzioni virtuali Abbinamento statico delle funzioni agli oggetti Statico: legato al tipo del puntatore, non al tipo dell’oggetto

puntato ‘casting’ per indicare esplicitamente il tipo del puntatore

Funzioni virtuali: Abbinamento dinamico della funzione all’oggetto I costruttori NON possono essere virtuali I distruttori possono invece esserlo: recuperano lo spazio

dell’oggetto puntato

Ricapitolando …

Page 130: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

130

Funzioni virtuali come base per la derivazione: Non definiscono il contenuto di alcuni metodi:

Public: virtual void stampa(){ };

Funzioni virtuali pure Definite ma mai utilizzate per istanziare oggetti Dichiarate con uno zero:

Public: virtual void stampa() = 0; Classe che contiene una o più funzioni virtuali pure :

classe astratta (indica com’è fatta la classe in modo astratto) Usata come base per la derivazione

Non è possibile istanziare da una classe astratta Una classe astratta è una interfaccia per la derivazione

Ricapitolando …

Page 131: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

131

Polimorfismo: capacità di rispondere in modo differenziato agli stessi comandi realizzato con overloading delle funzioni e con le funzioni virtuali

overloading delle funzioni: la scelta della funzione da attivare è effettuata esaminando una lista degli operandi o il tipo di oggetti tramite cui vengono operate le richieste alle operazioni

abbinamento statico(static binding): deciso alla compilazione

abbinamento dinamico(dynamic binding): deciso in run-time

overloading quando gli oggetti vengono rappresentati con puntatore: i puntatori possono puntare a oggetti di tipo diverso! ma l'abbinamento statico si basa sul tipo di puntatore e non sul tipo

di oggetto puntato! funzione virtuale: funzione il cui abbinamento con l'oggetto è fatto in

run-time

Polimorfismo e funzioni virtuali

Page 132: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

132

Una funzione definita virtuale nella classe base in una gerarchia di derivazione, rende virtuali tutte le funzioni con stesso prototipo e componenti la classe derivata

L'abbinamento dinamico oggetto-funzione con le funzioni virtuali funziona solo se gli oggetti sono gestiti con puntatore. Se l'oggetto gestito con il nome, l'associazione e' statica.

Tre casi in cui la chiamata di una funzione virtuale è risolta staticamente: quando la chiamata e’ effettuata con un oggetto e non con un

puntatore quando si usa scope (::) alla classe nella chiamata con puntatore quando una funzione virtuale è chiamata all'interno di costruttore

o distruttore Costruttori e distruttori virtuali

Un costruttore non puo’ essere mai dichiarato virtuale (deve essere dichiarato prima)

Distruttori possono essere virtuali!

Polimorfismo e funzioni virtuali

Page 133: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

133

Vantaggi del polimorfismo

Permette di scrivere codice generico che si adatta automaticamente alle specializzazioni future

Permette di creare nuovi metodi senza cambiare il resto del codice Semplice estensione del codice pre-esistente riutilizzabilita’ del codice Attenzione: se l’impostazione e’ corretta, si puo’ cambiare molto lavorando

poco… …se si modifica troppo il codice originale, l’impostazione e’ sbagliata! Modifiche concentrate migliore manutenzione Attenzione: i vantaggi si pagano con una certa perdita di efficienza!

Page 134: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

134

Polimorfismo (I)SuperficiePianadim1 : float

SuperficiePiana()presentati()Area()

triangolodim2 : float

triangolo()presentati()Area()

cerchio

cerchio()presentati()Area()

Page 135: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

135

Polimorfismo (II)

SuperficiePianadim1 : float

SuperficiePiana()presentati()Area()

triangolodim2 : float

triangolo()presentati()Area()

cerchio

cerchio()presentati()Area()

trapeziodim2 : floatdim3 : float

trapezio()presentati()Area()

Page 136: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

136

Lista non polimorfica senza friend

tipo_nodo

nodocognome : char [10]nome : char [10]anni : intcodice_fiscale : ints : tipo_studentestipendio : floatanni_quiescenza : int

nodo()nodo()set_attivi ta()set_cognome()set_nome()set_anni()set_cf()set_matricola()set_anno_corso()set_stipendio()set_quiescenza()set_next()get_attivi ta()get_cognome()get_nome()get_anni()get_cf()get_matricola()get_anno_corso()get_stipendio()get_quiescenza()get_next()

1

1

-attivita

1

0..1

-next

lista

l ista()insert()remove()stampa()

0..1

1

-radice

1

1

1

0..1

0..1

1

Page 137: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

137

Lista non polimorfica con friendtipo_nodo

nodocognome : char [10]nome : char [10]anni : intcodice_fiscale : ints : tipo_studentestipendio : floatanni_quiescenza : int

nodo()nodo()set_attivita()set_cognome()set_nome()set_anni()set_cf()set_matricola()set_anno_corso()set_stipendio()set_quiescenza()

1

1

-attivita

1

0..1

-next

lista

l ista()insert()remove()stampa()

0..1

1

-radice

1

11

0..1

0..1

1

Page 138: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

138

Inserimento di una categoria aggiuntiva nella lista non

polimorficatipo_nodo

nodocognome : char [10]nome : char [10]anni : intcodice_fiscale : ints : tipo_studentestipendio : floatanni_quiescenza : intdis : disocc

nodo()nodo()set_attivita()~nodo()set_cognome()set_nome()set_anni()set_cf()set_matricola()set_anno_corso()set_stipendio()set_quiescenza()set_disoc()set_impie()

1

1

-attivita

1

0..1

-next

lista

lista()~lista()insert()remove()stampa()

0..1

1

-radice

1

11

0..1

0..1

1

Page 139: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

139

Lista polimorfica

studentematricola : intanno_di_corso : int

studente()studente()stampa()insert()set_matricola()set_anno_corso()

lavoratorestipendio : float

lavoratore()lavoratore()stampa()insert()set_stipendio()

pensionatoanni_quiescenza : int

pensionato()pensionato()stampa()insert()set_quiescenza()

personacognome : char [10]nome : char [10]anni : intcodice_fiscale : int

persona()persona()set_cognome()~persona()set_nome()set_anni()set_cf()stampa()insert()

1

0..1

#ptr

1

0..1

#next

lista

lista()~lista()stampa()inserisci()rimuovi()

0..1

1

-radice

1

0..1

1

0..1

0..1

1

Page 140: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

140

//

//lista polimorfica. Header file

#include <iostream.h>

class persona

{

friend class lista;

protected:

char cognome[10];

char nome[10];

int anni;

int codice_fiscale;

persona *ptr;

persona *next;

public:

persona(char *co, char *no, int a, int cf);

persona();

~persona();

void set_cognome(char *c);

void set_nome(char *n);

void set_anni(int a);

void set_cf(int cf);

virtual void stampa();

virtual void insert();

};

Page 141: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

141

//(continua)

class studente:public persona

{

friend class lista;

private:

int matricola;

int anno_di_corso;

public:

studente(char *co, char *no, int a, int cf, int mat, int an):persona(co, no, a, cf)

{ matricola=mat; anno_di_corso=an; }

studente():persona()

{ matricola=0; anno_di_corso=0;}

void set_matricola(int m); void set_anno_corso(int ac);

void stampa(); void insert();

};

class lavoratore:public persona

{ friend class lista;

private:

float stipendio;

public:

lavoratore(char *co, char *no, int a, int cf, float s):persona(co, no, a, cf){stipendio=s;}

lavoratore():persona() { stipendio=0;}

void set_stipendio(float s);

void stampa(); void insert();

};

Page 142: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

142

//(continua)

class pensionato:public persona

{

friend class lista;

private:

int anni_quiescenza;

public:

pensionato(char *co, char *no, int a, int cf, int q):persona(co, no, a, cf)

{ anni_quiescenza=q; }

pensionato():persona()

{ anni_quiescenza=0;}

void set_quiescenza(int q);

void stampa();

void insert();

};

class lista

{

private:

persona *radice;

public:

lista();

~lista();

void inserisci(persona *n); void rimuovi(char *c); void stampa();

};

Page 143: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

143

//Lista polimorfica

//Implementazione dei metodi della lista polimorfica

#include <iostream.h>

#include "lista4.h"

persona::persona(char *co, char *no, int a, int cf)

{ strcpy(cognome,co); strcpy(nome,no);anni=a; codice_fiscale=cf; next=0; }

persona::persona()

{ strcpy(cognome,"\0"); strcpy(nome,"\0"); anni=0; codice_fiscale=0; next=0; }

persona::~persona(){};

void persona::set_cognome(char *c) { strcpy(cognome,c); }

void persona::set_nome(char *n) { strcpy(nome,n); }

void persona::set_anni(int a) { anni=a; }

void persona::set_cf(int cf) { codice_fiscale=cf; }

void persona::insert()

{ ptr=new persona(cognome, nome, anni, codice_fiscale); }

void persona::stampa()

{ cout << cognome << " " << nome << "\t anni " << anni << " CF= " << codice_fiscale ;}

void studente::set_matricola(int m) { matricola=m; }

void studente::set_anno_corso(int ac) { anno_di_corso=ac;}

void studente::stampa()

{ persona::stampa();

cout << " Studente, matricola=" << matricola << " anno di corso="<<anno_di_corso<<endl;

}

void studente::insert()

{ ptr=new studente(cognome, nome, anni, codice_fiscale, matricola, anno_di_corso); }

Page 144: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

144

//Lista polimorfica

void lavoratore::set_stipendio(float s)

{ stipendio=s; }

void lavoratore::stampa()

{ persona::stampa(); cout << " Lavoratore, stipendio=" << stipendio <<endl; }

void lavoratore::insert()

{ ptr=new lavoratore(cognome, nome, anni, codice_fiscale, stipendio); }

void pensionato::set_quiescenza(int q)

{ anni_quiescenza=q;}

void pensionato::stampa()

{ persona::stampa(); cout << " Pensionato, anni di quiescenza=" << anni_quiescenza <<endl;}

void pensionato::insert()

{ ptr=new pensionato(cognome, nome, anni, codice_fiscale, anni_quiescenza); }

lista::lista()

{ radice=0; }

lista::~lista()

{ // naturalmente per cancellare lo spazio degli oggetti bisogna avere una lista

// bidirezionale. Si lascia per esercizio

persona *p,*q;

do{ p=q=radice; while(p->next!=0){q=p;p=p->next;} q->next=0; delete p; } while(q!=radice);

delete radice;

}

Page 145: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

145

//(continua). Lista polimorfica

void lista::inserisci(persona *n)

{

persona *p, *q;

p=q=radice; n->insert();

if(p==0) {p=radice=n->ptr;} else { while(p!=0){q=p; p=p->next;} q->next=n->ptr; }

}

void lista::rimuovi(char *c)

{// in questo esempio non e' stata scritta. Si lascia per esercizio }

void lista::stampa()

{

persona *p;

p=radice; while(p!=0) { p->stampa(); p=p->next; }

}

main()

{

lista l; persona t;

studente st("Terreni", "Piero", 30, 2222, 23, 5);

lavoratore la("Pierucci", "Piero", 40, 1111, 2000);

pensionato pen("Rossi", "Luigi", 70, 3276, 5);

l.inserisci(&st); l.inserisci(&la); l.inserisci(&pen);

l.stampa();

}

Page 146: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

146

//Introduzione di una classe aggiuntiva. Lista polimorfica. Header file lista5.h

#include <iostream.h>

class persona

{

friend class lista;

protected:

char cognome[10];char nome[10];int anni;int codice_fiscale;persona *ptr;persona *next;

public:

persona(char *co, char *no, int a, int cf);

persona(); ~persona();

void set_cognome(char *c); void set_nome(char *n); void set_anni(int a);

void set_cf(int cf);

virtual void stampa(); virtual void insert();

};

class studente:public persona

{

friend class lista;

private:

int matricola; int anno_di_corso;

public:

studente(char *co, char *no, int a, int cf, int mat, int an):persona(co, no, a, cf)

{ matricola=mat; anno_di_corso=an; }

studente():persona() { matricola=0; anno_di_corso=0;}

void set_matricola(int m); void set_anno_corso(int ac); void stampa(); void insert();

};

Page 147: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

147

//lista5.h (continua)

class lavoratore:public persona

{

friend class lista;

private:

float stipendio;

public:

lavoratore(char *co, char *no, int a, int cf, float s):persona(co, no, a, cf)

{ stipendio=s; }

lavoratore():persona() { stipendio=0;}

void set_stipendio(float s); void stampa(); void insert();

};

class pensionato:public persona

{

friend class lista;

private:

int anni_quiescenza;

public:

pensionato(char *co, char *no, int a, int cf, int q):persona(co, no, a, cf)

{ anni_quiescenza=q; }

pensionato():persona() { anni_quiescenza=0;}

void set_quiescenza(int q); void stampa(); void insert();

};

Page 148: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

148

//lista5.h (continua) Classe aggiunta nell’header file

class disoccupato:public persona

{

friend class lista;

private:

int mesi_disoccupazione;

int nr_impieghi;

public:

disoccupato(char *co, char *no, int a, int cf, int md, int ni):persona(co, no, a, cf)

{ mesi_disoccupazione=md; nr_impieghi=ni; }

disoccupato():persona() { mesi_disoccupazione=0; nr_impieghi=0; }

void set_disoccupazione(int md) { mesi_disoccupazione=md; }

void set_impieghi(int ni) { nr_impieghi=ni; }

void stampa() { persona::stampa(); cout << " Disoccupato da " << mesi_disoccupazione;

cout << " mesi. Nr. impieghi=" << nr_impieghi << endl; }

void insert()

{ ptr=new disoccupato(cognome,nome,anni,codice_fiscale,mesi_disoccupazione,nr_impieghi); };

};

class lista

{ private:

persona *radice;

public:

lista(); ~lista(); void inserisci(persona *n); void rimuovi(char *c); void stampa();

};

Page 149: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

149

//implementazione dei metodi della lista polimorfica

#include <iostream.h>

#include "lista5.h"

persona::persona(char *co, char *no, int a, int cf)

{ strcpy(cognome,co); strcpy(nome,no); anni=a; codice_fiscale=cf; next=0; }

persona::persona()

{ strcpy(cognome,"\0"); strcpy(nome,"\0"); anni=0; codice_fiscale=0; next=0; }

persona::~persona(){};

void persona::set_cognome(char *c) { strcpy(cognome,c); }

void persona::set_nome(char *n) { strcpy(nome,n); }

void persona::set_anni(int a) { anni=a; }

void persona::set_cf(int cf) { codice_fiscale=cf; }

void persona::insert() { ptr=new persona(cognome, nome, anni, codice_fiscale); }

void persona::stampa()

{ cout << cognome << " " << nome << "\t anni " << anni << " CF= " << codice_fiscale ;}

void studente::set_matricola(int m) { matricola=m; }

void studente::set_anno_corso(int ac) { anno_di_corso=ac;}

void studente::stampa()

{

persona::stampa();

cout << " Studente, matricola=" << matricola << " anno di corso="<<anno_di_corso<<endl;

}

void studente::insert()

{ ptr=new studente(cognome, nome, anni, codice_fiscale, matricola, anno_di_corso); }

Page 150: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

150

//(continua)

void lavoratore::set_stipendio(float s) { stipendio=s; }

void lavoratore::stampa()

{ persona::stampa(); cout << " Lavoratore, stipendio=" << stipendio <<endl; }

void lavoratore::insert()

{ ptr=new lavoratore(cognome, nome, anni, codice_fiscale, stipendio); }

void pensionato::set_quiescenza(int q) { anni_quiescenza=q;}

void pensionato::stampa()

{ persona::stampa(); cout << " Pensionato, anni di quiescenza=" << anni_quiescenza <<endl;}

void pensionato::insert()

{ ptr=new pensionato(cognome, nome, anni, codice_fiscale, anni_quiescenza); }

lista::lista()

{ radice=0; }

lista::~lista()

persona *p,*q;

do{ p=q=radice; while(p->next!=0){q=p;p=p->next;} q->next=0; delete p; } while(q!=radice);

delete radice;

}

void lista::inserisci(persona *n)

{ persona *p, *q;

p=q=radice; n->insert();

if(p==0) {p=radice=n->ptr;} else { while(p!=0){q=p; p=p->next;} q->next=n->ptr; }

}

void lista::rimuovi(char *c)

{// in questo esempio non e' stata scritta. Si lascia per esercizio }

Page 151: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

151

//(continua)

void lista::stampa()

{

persona *p;

p=radice;

while(p!=0)

{ p->stampa(); p=p->next; }

}

main()

{

lista l; persona t;

studente st("Terreni", "Piero", 25, 2222, 23, 5);

lavoratore la("Pierucci", "Piero", 40, 1111, 2000);

pensionato pen("Rossi", "Luigi", 70, 3276, 5);

disoccupato dis("Ferri", "Luigi", 40, 2323, 8, 1);

l.inserisci(&st);

l.inserisci(&la);

l.inserisci(&pen);

l.inserisci(&dis);

l.stampa();

}

Page 152: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

152

Esempio di calcolo con i polinomi mediante programmazione ad oggetti

CFunction

CFunction()~CFunction()GetY()

CPolyOrder : intCoeffs : double*

CPoly()CPoly()CPoly()CPoly()~CPoly()GetY()Visual izza()operator =()operator +()operator -()GetOrder()operator *()GetCoeffs()

CPolyFnome : char*OrderF : intCoeffsF : double*

CPolyF()CPolyF()CPolyF()CPolyF()CPolyF()CPolyF()~CPolyF()GetY()Visual izza()operator =()operator +()operator -()operator *()SetNome()operator /()SetNum()SetDen()GetNome()Semplifica()

Page 153: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

153

class CFunction{ public: CFunction(){ if (dbg) cout << "Costruttore classe base CFunction" << endl;} virtual ~CFunction(){ if (dbg) cout << "Distruttore classe base CFunction" << endl;} virtual double GetY(double x) = 0;};

class CPoly: public CFunction{ protected: int Order; //Grado del polinomio double *Coeffs; public: CPoly(); //C default crea ma non definisce ordine e coefficienti CPoly(int g, double* c); //C numeratore grado g e coefficienti di *c, denominatore 1 CPoly(const CPoly& p); //C di copia CPoly(int g, double c); //costruttore di polinomio grado 0 coeff=c ~CPoly(); //Distruttore void Visualizza()const; //stampa CPoly &operator=(const CPoly& p); CPoly operator+(const CPoly& p); CPoly operator-(const CPoly& p); CPoly operator*(const CPoly& p); int GetOrder(); double GetCoeffs(int i); bool nullo(); //verifica se il polinomio è nulloù bool unitario(); double GetY(double x){}};

Page 154: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

154

class CPolyF: public CPoly{ //definisce polinomio base protected: char *nome; //nome del polinomio int OrderF; //Grado del polinomio double *CoeffsF; //Vettore di coefficienti public: CPolyF(); //C default crea ma non definisce ordine e coefficienti CPolyF(int g, double* c); //C numeratore grado g e coefficienti di *c, denominatore 1 CPolyF(int g, double* c, int gF, double *cF); //C numeratore grado g e coefficienti di *c, denominatore 1 CPolyF(const CPolyF& p); //C di copia CPolyF(const CPoly& a, const CPoly& b); //C per parti CPolyF(const CPoly& a); //C polinomi interi ~CPolyF(); //Distruttore void Visualizza()const; //stampa CPolyF &operator=(const CPolyF& p); //assegnazione CPolyF operator+(const CPolyF& p); //somma CPolyF operator-(const CPolyF& p); //differenza CPolyF operator*(const CPolyF& p); //moltiplicazione CPolyF operator/(const CPolyF& p); //divisione void SetNome(char *n); //assegna il nome al polinomio void SetNum(CPoly n); void SetDen(CPoly d); char* GetNome(); void Semplifica(); //ricerca fattori semplificabili //CPoly GetDen(); double GetY(double x){} //friend class CPolyF;};

Page 155: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

155

CPoly::CPoly(int g, double* c){ //Costruttore int i=0; for (i=g; i>0; i--){ //i coefficienti sono congruenti con il grado? if (c[i]==0) g--; else break; }//end for Order=g; if (g>=0){ Coeffs=new double[g+1]; for (i=0; i<=g; i++){ Coeffs[i]=c[i]; } } else Coeffs=NULL;}CPoly::~CPoly(){ //distruttore if (Coeffs) delete [] Coeffs; //se è definito CoeffsF lo dealloca}

void CPoly::Visualizza()const{ if (Order<0){ //polinomio definito? cout << "Polinomio non definito" << endl; return; }//end if stampa(Order, Coeffs); //stampa del solo numeratore //e stampa il risultato cout << endl; //a capo}

CPoly &CPoly::operator=(const CPoly& p){ if (Order!=p.Order){ if (Coeffs) delete [] Coeffs; Order=p.Order; Coeffs=new double[Order+1]; } //copia dei coefficienti for (int i=0; i<=Order; i++) Coeffs[i]=p.Coeffs[i]; if (dbg) cout << "\nOperatore CPoly =" << endl; return *this;}

Page 156: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

156

CPolyF::CPolyF():CPoly(){ //Costruttore di default nome=NULL; OrderF=-1; //denominatore CoeffsF=NULL; //nè per numeratore nè per denominatore if (dbg) cout << "C CPolyF default" << endl; //debug}

CPolyF &CPolyF::operator=(const CPolyF& p){ //se gli ordini sono diversi si devono riallocare i coefficienti if (Order!=p.Order){ if (Coeffs) delete [] Coeffs; //deallocando i precedenti Order=p.Order; //acquisendo il nuovo ordine Coeffs=new double[Order+1]; //e allocando quelli nuovi } //copia dei coefficienti for (int i=0; i<=Order; i++) Coeffs[i]=p.Coeffs[i]; if (OrderF!=p.OrderF){ if (CoeffsF) delete [] CoeffsF; //deallocando i precedenti OrderF=p.OrderF; //acquisendo il nuovo ordine CoeffsF=new double[OrderF+1]; //e allocando quelli nuovi } //copia dei coefficienti for (int i=0; i<=OrderF; i++) CoeffsF[i]=p.CoeffsF[i]; if (dbg) cout << "\nOperatore CPolyF =" << endl; return *this;

}

Page 157: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

157

CPolyF CPolyF::operator-(const CPolyF& p){ CPolyF ris; bool den_uguali=true; CPoly *n1, *d1, *n2, *d2; if (OrderF==p.OrderF){ for (int i=0; i<=p.OrderF; i++){ if (CoeffsF[i]!=p.CoeffsF[i]) den_uguali=false; } if (den_uguali){ n1=new CPoly(Order, Coeffs); n2=new CPoly(p.Order, p.Coeffs); d1=new CPoly(OrderF, CoeffsF); ris=CPolyF((*n1)-(*n2),(*d1)); delete n1, n2, d1; return ris; } } n1=new CPoly(Order, Coeffs); d1=new CPoly(OrderF, CoeffsF); n2=new CPoly(p.Order, p.Coeffs); d2=new CPoly(p.OrderF, p.CoeffsF); ris=CPolyF((*n1)*(*d2)-(*n2)*(*d1),(*d1)*(*d2)); delete n1 , n2, d1, d2; return ris;}

CPolyF CPolyF::operator+(const CPolyF& p){ CPolyF ris; bool den_uguali=true; CPoly *n1, *d1, *n2, *d2; if (OrderF==p.OrderF){ for (int i=0; i<=p.OrderF; i++){ if (CoeffsF[i]!=p.CoeffsF[i]) den_uguali=false; } if (den_uguali){ n1=new CPoly(Order, Coeffs); n2=new CPoly(p.Order, p.Coeffs); d1=new CPoly(OrderF, CoeffsF); ris=CPolyF((*n1)+(*n2),(*d1)); delete n1, n2, d1; return ris; } } n1=new CPoly(Order, Coeffs); d1=new CPoly(OrderF, CoeffsF); n2=new CPoly(p.Order, p.Coeffs); d2=new CPoly(p.OrderF, p.CoeffsF); ris=CPolyF((*n1)*(*d2)+(*n2)*(*d1),(*d1)*(*d2)); delete n1, n2, d1, d2; return ris;}

Page 158: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

158

CPolyF CPolyF::operator*(const CPolyF& p){ CPolyF ris; bool n1_d2_uguali=true; bool n2_d1_uguali=true; CPoly *n1, *d1, *n2, *d2; if (Order==p.OrderF){ //controllo uguaglianza num1-den2 for (int i=0; i<=p.OrderF; i++){ if (Coeffs[i]!=p.CoeffsF[i]){ n1_d2_uguali=false; break; } } } else n1_d2_uguali=false; if (n1_d2_uguali){ n1=new CPoly(0, 1); d2=new CPoly(0, 1); } else{ n1=new CPoly(Order, Coeffs); d2=new CPoly(p.OrderF, p.CoeffsF); } //fine uguaglianza num1-den2 if (OrderF==p.Order){ //controllo uguaglianza num2-den1 for (int i=0; i<=p.Order; i++){ if (CoeffsF[i]!=p.Coeffs[i]){ n2_d1_uguali=false; break; } } } else n2_d1_uguali=false; if (n2_d1_uguali){ n2=new CPoly(0, 1); d1=new CPoly(0, 1); } else{ n2=new CPoly(p.Order, p.Coeffs); d1=new CPoly(OrderF, CoeffsF); } //fine uguaglianza num2-den1 ris=CPolyF((*n1)*(*n2),(*d1)*(*d2)); delete n1, n2, d1, d2; return ris;}

Page 159: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

159

Esempio di calcolo vettoriale mediante programmazione ad oggetti

matrice_quadsim : intdiag : int

matrice_quad()matrice_quad()accedi()errore()stampa()check_sim()check_dia()

matrixr : intc : intm : int**

matrix()matrix()accedi()operator +()operator -()errore()operator *()stampa()

inte

vettoresize : int

vettore()vettore()operator +()operator -()errore()operator *()operator []()molt_per_matrice()operator |()scrivi()

0..1

1

-p0..1

1

Page 160: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

160

#include <iostream.h> //stream di input e output#include <stdlib.h> //libreria standard#include <conio.h> //console di input e output#include <math.h> //libreria con funzioni matematiche (radice)

typedef int inte; //Il vettore é di tipo intero

class matrix //classe matrice{ //definita da righe,colonne e dove sono colocate friend class vettore; //classe vettore può usare oggetti matrice protected: //protette per derivazione int r,c; //variabili numero righe(r) e colonne(c) int **m; //doppio puntatore public: matrix(int a,int b); //costruttore con argomenti numero righe e colonne matrix(matrix& y); //costruttore copia virtual inte& accedi(int i,int j); //accesso alle variabili:ne restituisce il valore matrix operator+(matrix& mat); //somma di 2 matrici;overloading di + matrix operator-(matrix& mat); //sottrazione di 2 matrici;overloading di - matrix operator*(matrix& mat); //moltiplicazione di 2 matrici;overloading di * void errore(char c[]); //segnala l'errore e esci dal programma virtual void stampa(char *s1); //visualizza la matrice};//matrix

matrix::matrix(int a,int b) //costruttore{ r=a; //assegna numero di righe c=b; //assegna numero di colonne m=new inte*[r]; //crea un "oggetto" di r puntatori,poi ad ogni puntatore for(int i=0;i<r;i++) //alloca una diversa riga { m[i]=new inte[c]; //l'i-esimo elemento di m(per ogni riga) diventa }//for i //un nuovo elemento di colonna}//costruttore

Page 161: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

161

class matrice_quad:public matrix //matrice quadrata,sottoclasse di matrice:è un esempio di derivazione{ //questo programma non richiede la dichiarazione friend,poiché nel main la classe vettore private: //non usa oggetti matrice_quad bool sim,diag; //variabili simmetrica e diagonale public: matrice_quad(int a,int b,bool si,bool dia):matrix(a,b) //costruttore che prende in { //derivazione numero di righe e di colonne(=righe) dal costruttore della superclasse matrice sim=si; //inizializzate le variabili simmetrica e diagonale diag=dia; }//costruttore matrice_quad(matrice_quad& x):matrix(x) //costruttore copia con derivazione { //delle protected di matrice e sim=x.sim; //private di matrice quadrata diag=x.diag; }//costruttore copia void check_sim(); //controlla se simmetrica void check_dia(); //controlla se diagonale inte& accedi(int i,int j); //accedi alle variabili void errore(char c[]); //segnala l'errore e esci dal programma void stampa(char *s1); //visualizza la matrice quadrata};//matrice_quad

class vettore //classe vettore{ //definita dal numero di elementi(size) e dove sono collocati(*p) private: int size; //quanti elementi ci sono inte *p; //dove sono questi elementi public: vettore(int n); //costruttore con argomento numero di elementi vettore(vettore& v); // costruttore copia inte& operator[](int i); //accesso all'elemento i-esimo vettore operator+(vettore& v); //somma di 2 vettori;overloading di + vettore operator-(vettore& v); //sottrazione di 2 vettori;overloading di - inte operator*(vettore& v); //prodotto scalare;overloading di * inte operator|(vettore& v); //calcolo del modulo del vettore;overloading di | vettore molt_per_matrice(vettore& v,matrix& mat); //moltiplicazione di 1 vettore per una matrice void errore(char c[]); //segnala l'errore e esci dal programma void scrivi(char *s1); //visualizza il vettore};//vettore

Page 162: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

162

matrix matrix::operator+(matrix& mat) //somma di matrici con overloading{ matrix loc(mat); //crea una copia locale di matrice if(mat.r!=r) //se il numero delle righe delle 2 matrici non coincide { mat.errore("matrici con numero di righe incompatibili"); //messaggio di errore }//if if(mat.c!=c) //se il numero delle colonne delle 2 matrici non coincide { mat.errore("matrici con numero di colonne incompatibili"); //messaggio di errore }//if for(int i=0;i<r;i++) //ciclo di riga { for(int j=0;j<c;j++) //ciclo di colonna { loc.m[i][j]=m[i][j]+mat.m[i][j]; //somma gli elementi delle 2 matrici }//for j }//for i return loc; //restituisci la matrice "somma"}//operator+

matrix matrix::operator-(matrix& mat) //sottrazione di matrici con overloading{ matrix loc(mat); //crea una copia locale di matrice if(mat.r!=r) //se il numero delle righe delle 2 matrici non coincide { mat.errore("matrici con numero di righe incompatibili"); //messaggio di errore }//if if(mat.c!=c) //se il numero delle colonne delle 2 matrici non coincide { mat.errore("matrici con numero di colonne incompatibili"); //messaggio di errore

}//if for(int i=0;i<r;i++) //ciclo di riga { for(int j=0;j<c;j++) //ciclo di colonna { loc.m[i][j]=m[i][j]-mat.m[i][j]; //sottrai agli elementi,quelli della matrice in entrata }//for j }//for i return loc; //restituisci la matrice "differenza"}//operator-

Page 163: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

163

matrix matrix::operator*(matrix& mat) //moltiplica 2 matrici;overloading di *{ matrix loc(mat); //crea una copia locale di matrice if(c!=mat.r) //se il numero di colonne della prima é diverso dal { //numero di righe della seconda mat.errore("Errore!Matrici incompatibili per il prodotto"); //messaggio di errore }//if for(int i=0;i<r;i++) //finché ho righe da completare { for(int j=0;j<mat.c;j++) //finché ho colonne da completare { loc.m[i][j]=0; //azzero il valore degli elementi for(int k=0;k<mat.r;k++) //finché ho righe della matrice in entrata { //faccio la somma del prodotto dell'elemento di riga i e colonna k loc.m[i][j]=loc.m[i][j]+m[i][k]*mat.m[k][j]; //per l'elemento di riga k e colonna j della }//for k //matrice in entrata }//for j }//for i return loc; //restituisci la matrice "prodotto"}//operator*

void matrix::stampa(char *s1) //visualizza{ cout << "la matrice " << s1 << ": \n"; for(int i=0;i<r;i++) //finché ho righe { for(int j=0;j<c;j++) //finché ho colonne { cout << m[i][j] << ' '; }//for j cout << '\n'; //vai a capo }//for i}//stampa

void matrice_quad::stampa(char *s1) //visualizza{ matrix::stampa(s1); //chiama la stampa di matrix passandogli la stringa s1 cout << "quadrata di ordine " << r << 'x' << c << " " ; //aggiungi le informazioni check_sim(); //su simmetrica e check_dia(); //diagonale}//stampa

Page 164: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

164

vettore::vettore(int n) //costruttore di vettore a n elementi{ size=n; //assegna il numero di elementi p=new inte[n]; //crea un vettore di n elementi}// costruttore

inte& vettore::operator[](int i) //accesso all'i-esimo elemento del vettore;overloading di []{ if((i<0)||(i>=size)) //se l'indice è sbagliato { cout << "L'indice del vettore é errato!"; //messaggio di errore }//if return (p[i]); //restituisci l'elemento i-esimo}//operator[]

vettore vettore::operator+(vettore& v) //somma 2 vettori;overloading di +{ vettore loc(v); //crea una copia locale del vettore in entrata if(v.size != size) //se il numero di elementi dei 2 vettori non coincide { v.errore("I vettori sono incompatibili e non si possono sommare"); //messaggio di errore }//if for(int i=0; i<size;i++) //finché ho elementi { loc.p[i]=p[i]+v.p[i]; //aggiungo il corrispondente elemento della }//for //matrice in entrata return loc; //restituisci il vettore "somma"}//operator+

vettore vettore::operator-(vettore& v) //sottrazione di vettori;overloading di -{ vettore loc(v); //crea copia locale di vettore in entrata if(v.size!=size) //se il numero di elementi dei 2 vettori non coincide { v.errore("I vettori sono incompatibili e non si possono sottrarre"); //messaggio di errore }//if for(int i=0;i<size;i++) //finché ho elementi { loc.p[i]=p[i]-v.p[i]; //sottraggo dagli elementi del vettore,quelli del }//for //vettore in entrata return loc; //restituisci il vettore "differenza"}// operator-

Page 165: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

165

inte vettore::operator*(vettore& v) //prodotto scalare dei vettori;overloading di *{ if(v.size!=size) //se il numero di elementi dei 2 vettori non coincide { v.errore("I due vettori sono incompatibili e non si possono moltiplicare"); //messaggio di errore }//if inte s=0; //inizializza e azzera il valore del prodotto scalare for(int i=0;i<size;i++) //finché ho elementi { s=s+p[i]*v.p[i]; //somma il prodotto dell'elemento i-esimo del }//for //vettore con lo stesso del vettore in entrata return s; //restituisci il valore del prodotto scalare}//operator*

inte vettore::operator|(vettore& v) //calcola il modulo del vettore{ inte a=0; //inizializza e azzera il valore del modulo del vettore for(int i=0;i<size;i++) //finché ho elementi { a=a+v.p[i]*v.p[i]; //somma i quadrati di tutti gli elementi }//for return sqrt(a); //restituiscine la radice}//operator|

vettore vettore::molt_per_matrice(vettore& v,matrix& mat) //moltiplica un vettore{ //per una matrice vettore loc(v); //crea una copia locale del vettore in entrata if(size!=mat.r) //se il numero di elementi del vettore è diverso { //dal numero di righe della matrice v.errore("Errore!Il prodotto tra vettore e matrice non é possibile!"); //messaggio di errore }//if for(int i=0;i<size;i++) //finché ho elementi nel vettore { loc.p[i]=0; //azzero il valore dell'elemento i-esimo del vettore risultante for(int k=0;k<mat.r;k++) //finché ho righe della matrice in entrata { loc.p[i]=loc.p[i]+p[k]*mat.m[k][i]; //sommo il prodotto dell'elemento }//for k //k-esimo del vettore con l'elemento }//for i //di riga k e colonna i della matrice return loc; //restituisci il vettore "prodotto" V x M}//molt_per_matrice

Page 166: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

166

void main() //esempio di main {//definizione variabili vettore v1(d),v2(d); //costruisce 2 vettori di dimensione d//leggi i valori dei vettori cin >> v1[i]; //inserisco i valori degli elementi del primo vettore da tastiera cin >> v2[i]; //inserisco i valori degli elementi del secondo vettore da tastiera// v1=v1+v2; //somma i 2 vettori// v1=v1-v2; //sottrai i 2 vettori// dato=v1*v2; //moltiplica i 2 vettori// dato=v1|v1; //calcola il modulo del primo vettore// matrix m1(h,k); //crea l'oggetto matrice m1//leggi i valori della matrice cin >> m1.accedi(i,j); //assegna i valori consecutivi a m1// matrix m2(a,b); //crea l'oggetto matrice m2//leggi i valori cin >> m2.accedi(i,j); //assegna i valori consecutivi a m2// m1=m1+m2; //somma m1 con m2,assegna il risultato a m1// m1=m1-m2; //sottrai m2 a m1,assegna il risultato a m1// m1=m1*m2; //moltiplica m1 con m2,assegna il risultato a m1// v1=v1.molt_per_matrice(v1,m1); //moltiplica v1 per m1,assegna il risultato// matrice_quad t(h,h,0,0),t1(h,h,0,0); //costruisci 2 matrici quadrate//leggi i valori cin >> t.accedi(i,j); //inserisci i valori della prima cin >> t1.accedi(i,j); //inserisci i valori della seconda}//main

Page 167: 1 Introduzione alla programmazione ad oggetti E.Mumolo, DEEI mumolo@units.it

167

scrivi il numero di elementi dei vettori:3scrivi i valori del primo vettore:1 2 3scrivi i valori del secondo vettore:4 5 6il vettore v1: 1 2 3 il vettore v2: 4 5 6 dopo la somma v1 modificato=v1+v2 il vettore v1: 5 7 9 dopo la differenza v1 modificato=v1-v2 il vettore v1: 1 2 3 Il prodotto scalare di v1 vale 32Il modulo di v1 é:3Scrivi rispettivamente il numero di righe e di colonne della prima matrice:3 3scrivi i valori della prima matrice:1 2 3 4 5 6 7 8 9 la matrice m1: 1 2 3 4 5 6 7 8 9 Scrivi rispettivamente il numero di righe e di colonne della seconda matrice:3 3scrivi i valori della seconda matrice:9 8 7 6 5 4 3 2 1 la matrice m2: 9 8 7 6 5 4 3 2 1 dopo la somma m1 modificata=m1+m2 la matrice m1: 10 10 10 10 10 10 10 10 10 ...

Esempio di utilizzo