1 / 190

Introduzione alla Object Oriented Programming, OOP

Introduzione alla Object Oriented Programming, OOP. E.Mumolo. DEEI mumolo@univ.trieste.it. Prima parte: il C++ come estensione del C. Paradigmi di programmazione. Modello procedurale Il mondo della programmazione viene visto come un sistema di processi Modello ad oggetti

zorion
Download Presentation

Introduzione alla Object Oriented Programming, OOP

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Introduzione alla Object Oriented Programming, OOP E.Mumolo. DEEI mumolo@univ.trieste.it

  2. Prima parte: il C++ come estensione del C

  3. 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

  4. Struttura di un programma • Spaghetti code • Programmazione strutturata

  5. Il linguaggio C++ • sviluppato alla AT&T da B.Stroustrup (1980) da una idea di Simula65. • 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) 

  6. 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

  7. àfor(int i=0; i<N; i++) {...} • Dichiarazioni variabili: non solo all’inizio del programma, ma anche nei cicli • Definizione di struttura, enum, unione

  8. 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

  9. 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

  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. //esempio di programmazione C++ : bubble sorting //oop13.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, ord1=5, ord2=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[ord1]; // definisce l'array SS di 5 strutture 'sistema' sistema *sis = new sistema[ord2]; // alloca in mem. lib. un array di 4 strutture int nl;

  14. //carica le strutture for(short i=0;i<ord1;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<ord2;i++){ sis[i].aa = new float[ord]; for(short j=0; j<ord;j++) sis[i].aa[j]=float(random(100)); } //primo caso cout << "\nPrimo caso“ << endl; for(short i=0;i<ord1;i++){ printf("\n\nArray 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("\nArray ordinato (nr. cicli=%d):\n", nl); for(short j=0;j<ord;j++) cout << SS[i].aa[j] << " "; cout ; // short } cout << "\n\nSECONDO CASO“ << endl; for(short i=0;i<ord2;i++){ printf("\n\nArray 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 } }

  15. 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("\nArray 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 }

  16. 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

  17. Seconda parte:Il C++ come linguaggio di programmazione ad oggetti

  18. 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

  19. 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

  20. 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 sistema tramite classi.

  21. Classe base (componente complesso) Classe base (componente minimo) Sottoclassi (componenti via via piu’ complesse) Sottoclassi (componenti minime) Automobile Specializzazione • Top-down:esempio • Bottom-up: carrozzeria ruota motore veicolo Generalizzazione Veicolo a motore Veicolo senza motore aereo auto moto taxi

  22. Campo variabili Metodo1 Metodo2 Metodo3 var. tua var. mia var. a Puntatore ‘this’ Puntatore ‘this’ Codice dei metodi Classi privato pubblico • 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

  23. Campo variabili Metodo1 Metodo2 Metodo3 Campo variabili Metodo1 Metodo2 Metodo3 Campo variabili Metodo1 Metodo2 Metodo3 Comunicazione tra oggetti Chiama tua.metodo2 a tua Chiama mia.metodo1 mia

  24. In conclusione • Il mondo visto come sistema ad oggetti: societa’ di entita’ attive, cooperanti, riutilizzabili • Progettazione bottom-up • Ereditarieta’, polimorfismo • Visione globale

  25. 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

  26. 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

  27. Osservazioni • 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 “->”:

  28. 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. 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

  29. struttura dati astratta punto

  30. 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

  31. 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.

  32. 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

  33. 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(); ...

  34. Costruttore con argomenti opzionali: #include <iostream.h> class stringa { int len; char *str; public: stringa(int a=0, char ch=' ') { len=a; str[len]='\0'; if(a>0) { str=new char[len+1]; for(int i=0; i<len; i++) str[i]=ch; } } };

  35. distruttori: funzioni che gestiscono la distruzione del contenuto di oggetti • utilizza il nome della classe preceduto da dal carattere ~ • attivata automaticamente al termine del ciclo di vita di un'oggetto • in genere usati per rilasciare la memoria dinamica oppure per salvare • informazioni su file • annulla quello fatto dal costruttore • libera la memoria addizionale utilizzata dell'oggetto • libera le risorse locale e chiude i file aperti • libera la memoria dinamica • il distruttore, come ogni metodo, può essere chiamato esplicitamente stringa *p=new stringa("nome"); p-> stringa:: ~stringa();

  36. //esempio diADT nodo ADT lista //oop23.cpp #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 };

  37. 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); } }

  38. 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 }

  39. 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'; }

  40. //esempio diADT Albero // File Albero.h #define NULL 0 struct nodo { int dato; nodo *sin,*des; }; class Albero { public: Albero() { radice = NULL; } protected: nodo* radice; }; //file AlbRic.h #include "Albero.h“ #include <iostream.h> class AlbRic : public Albero { public: AlbRic() {} ~AlbRic() { Cancella(radice); } void Inserisci(int i) { Aggiungi(i,radice); } void Visita(){ Differito(radice); } private: void Cancella(nodo * &p); void Aggiungi(int i, nodo* &p); void Differito(nodo *p); };

  41. // File oop24.cpp #include "AlbRic.h" void AlbRic::Cancella(nodo* &p) { if(p!=NULL) { Cancella(p->sin); Cancella(p->des); delete p; } } void AlbRic::Differito(nodo * p) { if(p!=0) { Differito(p->sin); Differito(p->des); cout << p->dato << " "; } } void AlbRic::Aggiungi(int i, nodo* &p) { if (p == NULL) { p = new nodo; p->dato = i; p->sin = NULL; p->des = NULL; } else if (i < p->dato) Aggiungi(i,p->sin); else if (i > p->dato) Aggiungi(i,p->des); } void main() { AlbRic a; for(int i=0;i<10;i++) a.Inserisci(i); a.Visita(); }

More Related