Introduzione alla Object Oriented Programming OOP E Mumolo
Introduzione alla Object Oriented Programming, OOP E. Mumolo. DEEI mumolo@univ. trieste. it
Prima parte: il C++ come estensione del C 2
Paradigmi di programmazione • • • Modello procedurale • Il mondo della programmazione viene visto come un sistema di processi Modello ad oggetti • Il mondo viene visto come un sistema di cose Alcuni temi tipici del modello procedurale: • Processi • Sequenze di esecuzione • Diagrammi di flusso • Programmazione top-down • Programmazione strutturata • Algoritmi=strutture dati + programmazione strutturata • Linguaggi strutturati: Fortran, Cobol, Basic, 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 lnguaggi procedurali 3
Struttura di un programma • Spaghetti code • Programmazione strutturata 4
Il linguaggio C++ • • sviluppato alla AT&T da B. Stroustrup (1980) da una idea di Simula 65. estensione del C astrazione dei dati Pro: • • • estensione rispetto al linguaggio C Piu adatto del C a progetti complessi prestazioni elevate nonostante la complessità molteplici produttori Contro: • linguaggio complesso (non elimina le ridondanze di C, anzi ne introduce) • linguaggio ibrido: consente di continuare sviluppare codice tradizionale in C • non aiuta a programmare ad oggetti • recupero manuale della memoria (Garbage Collection) 5
Estensione del C • • commenti: delimitati da // per commenti su una riga, oltre a /* … */ più adatti a commenti su più righe costanti: variabili di sola lettura specificatore const 6
• Dichiarazioni variabili: non solo all’inizio del programma, ma anche nei cicli for(int i=0; i<N; i++) {. . . } • Definizione di struttura, enum, unione 7
• Riferimenti (specificatore &) • 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 8
• Uso dei riferimenti come argomenti e risultati di funzione senza passare esplicitamente l’indirizzo //opp 4. 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=" << incrementa(i, i) << " i=" << i << 'n'; } Output: i=7 i=8 i=9 i=8 9
10
• argomenti di default in una funzione • 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 dichiarati nelle funzioni sono visibili 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 11
• • • 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 12
• Allocazione di oggetti dinamici nella memoria libera • • • Operatore new: argomento tipo dell’oggetto e ritorna un puntatore all’oggetto New restituisce un puntatore nullo in caso di errore Per allocare un array indicare tipo e numero di elementi Operatore delete: rilascia un oggetto in memoria libera Per rilasciare un array: specificatore [] 13
14
15
16
17
//esempio di programmazione C++ : bubble sorting //oop 13. cpp #include <stdio. h> #include <iostream. h> #include <stdlib. h> #include <string. h> float arry[10]={15. 5, 44, 0. 5, -1. 5, 65, 0. 0, 55. 5, 67. 0, 5, 3}; struct sistema { float *aa; int ord; }; const int ord=10, ord 1=5, ord 2=4; // variabili non modificabili! int bubble(float *, int N=ord); void scambia(float &, float &); // passaggio per riferimento void stampa(int); void stampa(float *a, int n=ord); main() { sistema SS[ord 1]; // definisce l'array SS di 5 strutture 'sistema' sistema *sis = new sistema[ord 2]; // alloca in mem. lib. un array di 4 strutture int nl; 18
//carica le strutture for(short i=0; i<ord 1; i++){ SS[i]. aa = new float[ord]; //alloca nella memoria libera for(short j=0; j<ord; j++) SS[i]. aa[j]=float(random(100)); } for(short i=0; i<ord 2; i++){ sis[i]. aa = new float[ord]; for(short j=0; j<ord; j++) sis[i]. aa[j]=float(random(100)); } //primo caso cout << "n. Primo caso“ << endl; for(short i=0; i<ord 1; i++){ printf("nn. Array originale %d: n", i); for(short j=0; j<ord; j++) cout << SS[i]. aa[j] << " "; cout ; // short nl=bubble(SS[i]. aa); // argomento di default printf("n. Array ordinato (nr. cicli=%d): n", nl); for(short j=0; j<ord; j++) cout << SS[i]. aa[j] << " "; cout ; // short } cout << "nn. SECONDO CASO“ << endl; for(short i=0; i<ord 2; i++){ printf("nn. Array originale %d: n", i); stampa(sis[i]. aa); nl=bubble(sis[i]. aa); //argomento di default: l'ordine dell'array stampa(nl); //overloading di funzioni e valori default stampa(sis[i]. aa); //overloading di funzioni e valori default } } 19
int bubble(float *A, int N) { char *flag="notsorted"; int nloop=0; while(!strcmp(flag, "notsorted")){ flag="sorted"; nloop++; for(short i=0; i<N-1; i++) if(*(A+i) > *(A+i+1)){ //A[i] e' *(A+i) scambia(*(A+i), *(A+i+1)); //passa per riferimento!! flag="notsorted"; } } return nloop; } void scambia(float &a, float &b) // il compilatore passa l'indirizzo delle var. { float temp=a; a=b; b=temp; } void stampa(int n) { printf("n. Array ordinato (nr. cicli=%d): n", n); } void stampa(float *a, int n) { for(short j=0; j<n; j++) cout << a[j] << " "; cout ; // definizione short } 20
• Sovrapposizione delle funzioni (overloading) • stesso nome per funzioni diverse, che devono avere argomenti diversi in numero e tipo • lo stesso nome deve avere lo stesso tipo di risultato 21
Seconda parte: Il C++ come linguaggio di programmazione ad oggetti 22
Il modello ad oggetti • • Alcuni temi tipici • Dalla astrazione funzionale alla astrazione dei dati • Il mondo e’ modellato non come processi, ma cose • Societa’ di entita’ attive, cooperanti, riusabili • Progettazione bottom-up non top-down • Modelli di classi, sottoclassi, istanze di oggetti • Linguaggi ad oggetti: Simula, Smalltalk, Eiffel, C++, Java OOP: incapsulamento e mascheramento dei dati • limitazione del campo di visibilità delle procedure che manipolano i dati • dati e procedure inseparabili oggetto • procedure di un oggetto (metodi) attivate inviando messaggi all'oggetto • gli oggetti inviano messaggi ad altri oggetti • punti fondamentali: tipi di dati astratti, classe, oggetti, incapsulamento, gerarchie di tipi (sottoclassi), ereditarietà, polimorfismo 23
• • • OOP focalizza l'attenzione sui dati da manipolare, piuttosto che sulle procedure obiettivi della progettazione e realizzazione di software mediante OOP : • migliorare la produttività del programmatore • aumentare la versatilità e la riutilizzazione del software • controllare la complessità • diminuire il costo di manutenzione oggetto = contenitore che racchiude dati e funzioni che gestiscono i dati • Information hiding: capacità di oggetti di racchiude dati per eliminare accessi indebiti • interfaccia dell'oggetto: indica e pubblicizza le operazioni autorizzate ad accedere i dati • implementazione delle funzioni (codice): è in genere nascosto all'interno dell'oggetto • un oggetto riceve delle richieste e risponde alle stesse 24
• classe = definizione astratta delle caratteristiche degli oggetti • gli oggetti sono tra loro distinti anche se derivano dalla stessa classe • creazione di un oggetto: definizione di una variabile appartenente ad una determinata classe, o definizione di un oggetto di tipo classe nella memoria libera • l'interfaccia di una classe è costituita da tutto ciò che non è nascosto in un oggetto. L'interfaccia resta in genere inalterata nel tempo • operare con gli oggetti : • divisione in componenti che contengono dati e procedure che operano sui dati • un oggetto contiene quindi sia la struttura dati che le procedure (metodi) che definiscono il comportamento dell'oggetto stesso • le strutture dati sono nascoste all'interno degli oggetti • il mondo esterno comunica con i oggetti inviando loro delle richieste • (messaggi) per informare l'oggetto su quello che deve essere fatto non su come viene fatto • suddivisione del software in classi: un sistema di archiviazione viene chiamato classe archivio con struttura dati e metodi per modificare dati • operare con gli oggetti : • ogni procedura e’ associata ad una classe • se si aggiungono funzioni di un insieme esistente, si può creare una sottoclasse, creare una nuova classe, o aggiungerle alla classe esistente • struttura gerarchica di tipi e sottotipi mediante scomposizione top-down o bottom-up: identificazione e rappresentazione dei dati piu’ importanti del 25 sistema tramite classi.
• Top-down: esempio Specializzazione Classe base (componente complesso) Automobile ruota carrozzeria motore • Bottom-up: Classe base (componente minimo) Generalizzazione Sottoclassi (componenti minime) veicolo Veicolo a motore Veicolo senza motore moto Sottoclassi (componenti via piu’ complesse) auto taxi aereo 26
Classi • Una classe (ADT): class casa {. . . }; • • • Campo variabili Metodo 1 Metodo 2 Metodo 3 privato pubblico 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; var. a var. mia Puntatore ‘this’ var. tua Puntatore ‘this’ Codice dei metodi • • mia. metodo 1; //attiva metodo 1 mediante l’invio dell’indirizzo di mia al codice di metodo 1 Comunicazione tra oggetti tramite invio di messaggi di attivazione 27
Comunicazione tra oggetti Campo variabili Metodo 1 Metodo 2 Metodo 3 Chiama tua. metodo 2 a Campo variabili Metodo 1 Metodo 2 Metodo 3 tua Chiama mia. metodo 1 mia 28
In conclusione • Il mondo visto come sistema ad oggetti: societa’ di entita’ attive, cooperanti, riutilizzabili • Progettazione bottom-up • Ereditarieta’, polimorfismo • Visione globale 29
Le classi in C++ • • 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 lo specificatore private è implicito scope di una classe: visibilita’ dei componenti (funzioni e variabili) sintatticamente la classe puo’ essere vista come una estensione di struct 30
• • 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” //file contatore. h 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 31
32
33
34
35
• Osservazioni i metodi vengono attivati inviando all'oggetto un messaggio con il nome del metodo usando l’operatore punto “. ”: • c 1. incrementa(); //invia all’oggetto c 1 la richiesta di attivare //incrementa • c 1. visualizza(); //analogamente • Puntatore ad oggetto: operatore freccia a destra “->”: 36
Osservazioni (cont. ) • • • 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. c 1. 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 c 1, c 2; c 1. valore++; c 2. valore++; } • ma: in questa forma i dati sono pubblici e la funzione principale accede direttamente al dato sottostante 37
• struttura dati astratta punto 38
• • • Classi annidate (nested) classe interna o nested: definita all’interno di un’altra classe visibilita’: all’interno dello scope della classe che la contiene classi definite all’interno di una funzione (scope locale) visibile solo all’interno della funzione 39
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 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. 40
• Costruttore di default • funzione senza argomenti formali • chiamata dal compilatore quando viene definita una variabile senza inizializzazione speciale • nel caso si richeda una inizializzazione speciale costruttore con argomenti 41
• Costruttore con argomenti: il costruttore da utilizzare dipende dalla lista degli argomenti • variabili dinamiche stringa *ps=new stringa(“iniziale”); //new attiva il costruttore. Se new fallisce, ps punta a //NULL e il compilatore NON attiva il costruttore ps->stampa(); . . . 42
• Costruttore con argomenti opzionali: #include <iostream. h> class stringa { int len; char *str; public: stringa(int a=0, char ch=' ') { len=a; str[len]='