1 laboratorio di calcolo II AA 2003/04 quinta settimana a cura di Domizia Orestano Dipartimento di Fisica Stanza 159 - tel. (06 5517) 7281 www.fis.uniroma3.it/~orestano.

Slides:



Advertisements
Presentazioni simili
Programmazione ad oggetti
Advertisements

Funzioni Friend Come abbiamo visto non possiamo accedere a membri privati di una classe dall'esterno della classe. Ma a volte abbiamo bisogno di farlo.
© 2007 SEI-Società Editrice Internazionale, Apogeo Unit à B2 Gli oggetti: concetti avanzati.
© 2007 SEI-Società Editrice Internazionale, Apogeo Unità B1 Le basi della programmazione a oggetti.
Recupero debito quarto anno Primo incontro
Recupero debito quarto anno Secondo incontro
Informatica Recupero debito quarto anno Terzo incontro.
Informatica 2 Lezione 4 Corso di laurea in matematica Informatica 2 Dott. Ing. Leonardo Vito Corso di laurea matematica indirizzo matematica per le applicazioni.
Differenze nei vari linguaggi di Elisa Trifirò e Barbara Tacchino
Le gerarchie di tipi.
Introduzione al linguaggio C
Introduzione al linguaggio C Dr. Francesco Fabozzi Corso di Informatica.
1 Programmazione ad oggetti in Java E.Mumolo, DEEI
Introduzione al linguaggio C++ 5 lezioni
Introduzione al linguaggio Java
Derivazione tra classi
Overriding.
Oggetti e dati primitivi
Programmazione Corso di laurea in Informatica
Gerarchia di classi Java
1 Le gerarchie di tipi. 2 Supertipi e sottotipi 4 un supertipo –class –interface 4 può avere più sottotipi –un sottotipo extends il supertipo ( class.
Lab. Calc. 2005/06 Ereditarietà. Lab. Calc. 2005/06 Scopo di questa lezione: Imparare a creare nuove classi ereditando da classi già esistenti. Capire.
1 laboratorio di calcolo II AA 2003/04 sesta settimana a cura di Domizia Orestano Dipartimento di Fisica Stanza tel. ( )
1 laboratorio di calcolo II AA 2003/04 terza settimana a cura di Domizia Orestano Dipartimento di Fisica Stanza tel. ( )
1 laboratorio di calcolo II AA 2003/04 a cura di Domizia Orestano Dipartimento di Fisica Stanza tel. ( )
1 laboratorio di calcolo II AA 2003/04 nona settimana a cura di Domizia Orestano Dipartimento di Fisica Stanza tel. ( )
1 laboratorio di calcolo II AA 2003/04 quarta settimana a cura di Domizia Orestano Dipartimento di Fisica Stanza tel. ( )
1 laboratorio di calcolo II AA 2003/04 seconda settimana a cura di Domizia Orestano Dipartimento di Fisica Stanza tel. ( )
1 Ereditarietà Una classe può essere derivata da una classe esistente usando la sintassi: public, protected e private specificano il tipo di accesso ai.
Le classi Definizione di classe Attributi e metodi di una classe Costruttori e distruttori Private e public Funzioni friend Il puntatore this.
Esercizi Puntatori, struct con campi puntatore, puntatori a struct, rapporto tra array e puntatori. FUNZIONI Passaggio di parametri per indirizzo, passaggio.
Java base IV: Java e la programmazione O.O.
IL TEMA DELLA RIUSABILITÀ Si vuole riusare tutto ciò che può essere riusato (componenti, codice, astrazioni) Non è utile né opportuno modificare codice.
Elementi di programmazione ad oggetti a. a. 2009/2010 Corso di Laurea Magistrale in Ingegneria Elettronica Docente: Mauro Mazzieri, Dipartimento di Ingegneria.
Elementi di programmazione ad oggetti a. a. 2009/2010 Corso di Laurea Magistrale in Ingegneria Elettronica Docente: Mauro Mazzieri, Dipartimento di Ingegneria.
Programmazione in Java (8)
Ereditarietà e Polimorfismo
Introduzione alla programmazione Object Oriented
ISTITUTO STATALE DI ISTRUZIONE SUPERIORE F. ENRIQUES CORSO JAVA – PROVA INTERMEDIA DEL 12 MARZO 2007 NOME: COGNOME: ________________________________________________________________________________.
Enumerazioni e Classi 1. Enumerazioni Permettono di definire nuovi tipi che consistono in un insieme di valori costanti (ognuno con un nome) – Migliorano.
ISTITUTO STATALE DI ISTRUZIONE SUPERIORE F. ENRIQUES CORSO JAVA – PROVA INTERMEDIA DEL 12 MARZO 2007 NOME: COGNOME: ________________________________________________________________________________.
Corso di Programmazione Grafica e Laboratorio Daniele Marini
Fondamenti di Informatica 2 Ingegneria Informatica Docente: Giovanni Macchia a.a
1 FONDAMENTI DI INFORMATICA II Ingegneria Gestionale a.a ° Ciclo Approfondimenti sulle Classi.
1 FONDAMENTI DI INFORMATICA II Ingegneria Gestionale a.a ° Ciclo Polimorfismo.
1 FONDAMENTI DI INFORMATICA II Ingegneria Gestionale a.a ° Ciclo Ereditarietà.
Università degli Studi di Napoli Parthenope programmazione III.
Programmazione a oggetti
CORSO DI PROGRAMMAZIONE II Lezione 22
Lezione 1 Panoramica sui paradigmi di programmazione
Oggetti in C# Lezione 5 Polimorfismo I Andrea Zoccheddu.
Programmazione ad oggetti
Vettori, indirizzi e puntatori Finora abbiamo usato gli indirizzi nel chiamare  la funzione scanf()  le altre funzioni per riferimento Tuttavia la vera.
Ereditarieta’. Contenuti Introduciamo un meccanismo fondamentale di Java: l’ereditarieta’ Permette di estendere classi gia’ definite (ovvero di definire.
1 Osservazioni Generali Struttura di programma Gerarchia di classi: overloading, overriding, e dispatching Analisi ed esecuzione Modificabilità e condivisione.
Fondamenti di Informatica II Ingegneria Informatica Prof. M.T. PAZIENZA a.a – 3° ciclo.
Fondamenti di Informatica 2 Ingegneria Informatica Docente: Giovanni Macchia a.a
Fondamenti di Informatica 2 Ingegneria Informatica Docente: Giovanni Macchia a.a
Fondamenti di informatica Oggetti e Java Luca Cabibbo Luca Cabibbo – Fondamenti di informatica: Oggetti e Java Copyright © 2004 – The McGraw-Hill Companies.
Fondamenti di Informatica 2 Ingegneria Informatica (A-I) Prof. M.T. PAZIENZA a.a – 3° ciclo.
1 Semantica Operazionale di un frammento di Java: intro estensione (con piccole varianti) di quella di FP | v |
1 FONDAMENTI DI INFORMATICA II Ingegneria Gestionale a.a ° Ciclo Strutture e Classi.
Corso di Algoritmi e Strutture Dati con Laboratorio Richiami di Java – parte II.
Rapporto incrementale Calcolare il rapporto incrementale.
28/12/2001package 1 Package Pacchetti e interfacce.
Introduzione all’Ereditarietà Pietro Palladino. Richiami UML Classe: descrizione di un insieme di oggetti software con caratteristiche simili Definisce.
Introduzione alle Classi e agli Oggetti in Java 1.
Transcript della presentazione:

1 laboratorio di calcolo II AA 2003/04 quinta settimana a cura di Domizia Orestano Dipartimento di Fisica Stanza tel. ( ) UNIVERSITA DEGLI STUDI ROMA TRE DIPARTIMENTO DI FISICA E. AMALDI

2 sommario Ripasso degli argomenti trattati la settimana scorsa: ereditarietà, protezioni, polimorfismo e metodi virtuali, distruttori e distruttori virtuali, cosa abbiamo osservato nellesercitazione Un altro esempio che illustra nuovamente ereditarietà, polimorfismo e metodi virtuali, distruttori e distruttori virtuali, classi astratte Overloading Dei metodi e degli operatori, esempi

3 L'ereditarieta' in C++: Estensione delle caratteristiche di una classe: la classe derivata è un caso particolare della classe base con alcuni dettagli in più –la figura 2D e' un caso particolare di Figura –il Cerchio e' una figura 2D Adesione ad un modello: la classe base definisce le caratteristiche minimali che devono avere tutte le classi derivate –Se Figura ha un metodo che si chiama disegna tutte le classi che ereditano da Figura avranno un metodo disegna

4 Privati private PrivatiProtetti protected PrivatiProtettiPubblici public Attributi e Metodi Privati Attributi e Metodi Protetti Attributi e Metodi Pubblici Tipo di Ereditarieta Protezioni Affinché la classe derivata possa accedere agli attributi della classe base, senza violare lincapsulamento che nasconde gli attributi della classe base al resto del codice, questi devono essere dichiarati protected nella classe base. I clienti della classe derivata vedono i membri (attributi e metodi) della classe base con livelli di protezione che dipendono da come si è dichiarata la relazione di ereditarietà:

5 1. In presenza di metodi polimorfi, presenti con lo stesso prototipo in più classi legate da ereditarietà, per indicare al compilatore che deve cercare il metodo nella classe piu bassa nella catena gerarchica si usa la parola virtual 2. virtual va utilizzato nella classe piu alta nella catena gerarchica delle classi che devono utilizzare il polimorfismo (ma e bene ripeterlo anche nelle classi figlie) 3.Se un metodo e dichiarato virtual Il compilatore ricerca un metodo nella classe piu bassa nella catena di ereditarieta (esempio: calcolaPosizione(fx,fy,dt) ) Se non lo trova esegue il metodo nella classe piu alta (esempio: X() Vx() ) 4.Sintassi virtual void calcolaPosizione (float fx, float fy, float dt); ma anche virtual ~CorpoCeleste ( ); Metodi virtuali

6 Quando viene invocato il Costruttore di una Classe che eredita da altre, il compilatore invoca automaticamente i Costruttori di tutte le Classi nella catena di ereditarieta, inziando dal costruttore piu in alto nella catena gerarchica Quando viene invocato il Distruttore di una Classe che eredita da altre, il compilatore invoca automaticamente i Costruttori di tutte le Classi nella catena di ereditarieta, inziando dal costruttore piu in basso nella catena gerarchica Se ad un oggetto si accede tramite il suo puntatore, istanziato come puntatore di una delle classi madre, e necessario che il distruttore sia definito virtual, in modo che il compilatore inizi ad invocare il distruttore piu in basso nella catena di ereditarieta, risalendo poi tutta la catena gerarchica. Distruttori virtuali

7 Esercitazione della scorsa settimana Avete definito (.h) ed implementato (.cc) la classe Sonda che eredita da CorpoCeleste. Una Sonda è un CorpoCeleste con alcune caratteristiche in più (viene fatta partire dalla superficie di un CorpoCeleste con una certa velocità iniziale ad un istante fissato) e con una versione modificata del metodo calcolaPosizione. Per inserire oggetti della nuova classe nella simulazione del sistema solare è stato sufficiente instanziarli nel main e dichiararli con aggiungiPianeta alla classe SistemaSolare, non sono state necessarie modifiche a SistemaSolare.

8 #include "CorpoCeleste.h" class Sonda: public CorpoCeleste { protected: float tCount; float tStart; CorpoCeleste *owner; float svx; float svy; char started; public: Sonda(const char *name, float mass, float starttime, CorpoCeleste *startFrom, float vxi, float vyi); ~Sonda() { } ; void calcolaPosizione (float fx, float fy, float t); }; Sonda.h

9 #include "Sonda.h" #include Sonda::Sonda(const char *name, float mass, float starttime, CorpoCeleste * startFrom, float vxi, float vyi) : CorpoCeleste(name, mass, 0., 0., 0., 0.) { tStart = starttime ; tCount = 0 ; owner = startFrom ; svx = vxi ; svy = vyi ; started = 0 ; x = owner->X() ; y = owner->Y() ; vx = owner->Vx() ; vy = owner->Vy() ; } Sonda.cc prima parte

10 void Sonda::calcolaPosizione (float fx, float fy, float t) { if (tCount<tStart) { x = owner->X() ; y = owner->Y() ; vx = owner->Vx() ; vy = owner->Vy() ; } else { if (!started) { cerr << "Sonda in partenza...\n ; vx += svx ; vy += svy ; started = 1 ; } CorpoCeleste::calcolaPosizione(fx,fy,t); } tCount += t ; } Sonda.cc seconda parte

11 simula.cc

12 Alcune modifiche sono state invece apportate in CorpoCeleste.h: dichiarazione gli attributi protected anziché private chi se ne fosse scordato ha riscontrato un errore di compilazione quando Sonda cerca di accedere x, y, vx o vy (nel costruttore e in calcolaPosizione ) dichiarazione come virtual del metodo CorpoCeleste::calcolaPosizione altrimenti, in SistemaSolare::evolvi, listruzione pianeti[i]->calcolaPosizione((float)fx, (float)fy, dt); chiamerebbe sempre CorpoCeleste::calcolaPosizione, anche per i puntatori ad oggetti Sonda dichiazione come virtual del metodo CorpoCeleste::~CorpoCeleste per far chiamare Sonda ::~Sonda (che a sua volta chiama CorpoCeleste::~CorpoCeleste ) quando si effettui il delete di un puntatore ad un CorpoCeleste che sia anche un Sonda Chi ne ha avuto il tempo ha anche provato a rendere pure virtual un metodo di CorpoCeleste e dovrebbe avere osservato un problema nella compilazione del main: sole e terra non possono più essere istanziati!

13 #ifndef CORPOCELESTE_H #define CORPOCELESTE_H class CorpoCeleste { protected: char *Nome; double m; double x; double y; double vx; double vy; public: CorpoCeleste() ; CorpoCeleste (const char *nomeCorpo, float mass, float xpos, float ypos, float vxi, float vyi); virtual ~CorpoCeleste() ; virtual void calcolaPosizione (float fx, float fy, float t); void stampaPosizione(); void stampaVelocita() ; const char *nome() ; double M() ; double X() ; double Y() ; double Vx() ; double Vy() ; }; #endif CorpoCeleste.h con modifiche per ereditarietà

14 1.Se un metodo e dichiarato virtual, la classe che eredita (la classe piu bassa nella catena gerarchica) puo ridefinire il metodo, che e comunque implementato nella classe da cui si eredita 2.Se un metodo e dichiarato pure virtual ( virtual …. = 0 ; ) tutte le classi che ereditano devono fornire il metodo, che non e implementato nella classe da cui si eredita 3.Sintassi virtual double Area() = 0 ; 4.Una classe con almeno un metodo pure virtual si chiama classe astratta 5.Attenzione! Gli oggetti di una classe astratta non possono essere istanziati Metodi pure virtual e classi astratte

15 Supponiamo di avere tre classi (shape, cerchio e quadrato) legate tra loro da una relazione di Ereditarietà. shape cerchio quadrato Un altro esempio

16 #ifndef SHAPE_H #define SHAPE_H #include class shape { public: shape() {}; ~shape() { cout << " Distruggo una shape " << endl << endl ; }; void print() { cout << " Sono una shape" << endl ; }; #endif shape.h

17 #ifndef CERCHIO_H #define CERCHIO_H #include #include shape.h" class cerchio : public shape { public: cerchio() {}; ~cerchio() { cout << " Distruggo un cerchio " << endl << endl ; }; void print() { cout << " Sono un cerchio " << endl ; }; #endif cerchio.h

18 #ifndef QUADRATO_H #define QUADRATO_H #include #include "shape.h" class quadrato : public shape { public: quadrato() {}; ~quadrato() { cout << " Distruggo un quadrato " << endl << endl ; }; void print() { cout << " Sono un quadrato " << endl ; }; #endif quadrato.h

19 int main() { shape s; cerchio c; quadrato q; cout << endl; s.print(); c.print(); q.print(); shape * v[3]; v[0] = new shape; v[1] = new cerchio; v[2] = new quadrato; cout << endl; v[0]->print(); v[1]->print(); v[2]->print(); cout << " ================== " << endl ; cout << " Applico delete " << endl ; cout << shape 0 : " << endl; delete v[0]; cout << " shape 1 : " << endl; delete v[1]; cout << " shape 2 : " << endl; delete v[2]; cout << endl; cout << " =================== " << endl; return 0; }; Sono una shape Sono un cerchio Sono un quadrato Senza virtual

20 #ifndef SHAPE_H #define SHAPE_H #include class shape { public: shape() {}; ~shape() { cout << " Distruggo una shape " << endl << endl ; }; void print() { cout << " Sono una shape" << endl ; }; #endif shape.h virtual

21 int main() { shape s; cerchio c; quadrato q; cout << endl; s.print(); c.print(); q.print(); shape * v[3]; v[0] = new shape; v[1] = new cerchio; v[2] = new quadrato; cout << endl; v[0]->print(); v[1]->print(); v[2]->print(); cout << " ================== " << endl ; cout << " Applico delete " << endl ; cout << shape 0 : " << endl; delete v[0]; cout << " shape 1 : " << endl; delete v[1]; cout << " shape 2 : " << endl; delete v[2]; cout << endl; cout << " =================== " << endl; return 0; }; Sono una shape Sono un cerchio Sono un quadrato Con virtual Sono una shape Sono un cerchio Sono un quadrato

22 int main() { shape s; circle c; quadrato q; cout << endl; s.print(); c.print(); q.print(); shape * v[3]; v[0] = new shape; v[1] = new circle; v[2] = new quadrato; cout << endl; v[0]->print(); v[1]->print(); v[2]->print(); cout << " ================== " << endl ; cout << " Applico delete " << endl ; cout << shape 0 : " << endl; delete v[0]; cout << " shape 1 : " << endl; delete v[1]; cout << " shape 2 : " << endl; delete v[2]; cout << endl; cout << " =================== " << endl; return 0; }; Senza distruttore virtual Distruggo un quadrato Distruggo una shape Distruggo un cerchio Distruggo una shape ========================== Applico delete shape 0 : Distruggo una shape shape 1 : Distruggo una shape shape 2 : Distruggo una shape =========================

23 #ifndef SHAPE_H #define SHAPE_H #include class shape { public: shape() {}; ~shape() { cout << " Distruggo una shape " << endl << endl ; }; void print() { cout << " Sono una shape" << endl ; }; #endif shape.h virtual

24 Con distruttore virtual int main() { shape s; circle c; quadrato q; cout << endl; s.print(); c.print(); q.print(); shape * v[3]; v[0] = new shape; v[1] = new circle; v[2] = new quadrato; cout << endl; v[0]->print(); v[1]->print(); v[2]->print(); cout << " ================== " << endl ; cout << " Applico delete " << endl ; cout << shape 0 : " << endl; delete v[0]; cout << " shape 1 : " << endl; delete v[1]; cout << " shape 2 : " << endl; delete v[2]; cout << endl; cout << " =================== " << endl; return 0; }; Distruggo un quadrato Distruggo una shape Distruggo un cerchio Distruggo una shape ========================== Applico delete shape 0 : Distruggo una shape shape 1 : Distruggo un cerchio Distruggo una shape shape 2 : Distruggo un quadrato Distruggo una shape =========================

25 Supponiamo ora di voler aggiungere alle classi geometriche un metodo che determini larea della figura. Larea di una figura si calcola in modo diverso a seconda della sua forma. Dovremo quindi fornire una diversa implementazione di double Area( ) ; per ogni classe. Che metodo Area( ) mettiamo in shape? Ci mettiamo un metodo pure virtual che fornisce il modello per le classi derivate virtual double Area( ) = 0 ;

26 #ifndef SHAPE_H #define SHAPE_H #include class shape { public: shape() {}; virtual ~shape() { cout << " Distruggo una shape " << endl << endl ; }; virtual void print() { cout << " Sono una shape" << endl ; }; virtual double Area()=0; }; #endif shape.h

27 Se ora provassimo a compilare il main avremmo degli errori : 1.Gli oggetti di tipo cerchio e di tipo quadrato non sono validi perché non hanno il metodo Area 2.Gli oggetti di tipo shape non possono essere istanziati per lo stessso motivo Rimosso dal main loggetto di tipo shape aggiungiamo il metodo Area nelle classi derivate:

28 #ifndef CERCHIO_H #define CERCHIO_H #include #include shape.h #include class cerchio : public shape { private: double radius; public: cerchio(double r):radius(r) {}; ~cerchio() { cout << " Distruggo un cerchio " << endl << endl ; }; void print() { cout << " Sono un cerchio " << endl ; }; double Area() { return M_PI*radius*radius; }; #endif cerchio.h

29 #ifndef QUADRATO_H #define QUADRATO_H #include #include "shape.h" class quadrato : public shape { private: double side; public: quadrato(s):side(s) {}; ~quadrato() { cout << " Distruggo un quadrato " << endl << endl ; }; void print() { cout << " Sono un quadrato " << endl ; }; double Area() { return side*side; }; #endif quadrato.h

30 int main() { shape * v[2]; v[0] = new circle(1); v[1] = new quadrato(1); cout << endl; v[0]->print(); cout Area() <<endl; v[1]->print(); cout Area() <<endl; cout << " ================== " << endl ; cout << " Applico delete " << endl ; cout << " shape 0 : " << endl; delete v[0]; cout << " shape 1 : " << endl; delete v[1]; cout << endl; cout << " =================== " << endl; return 0; };

31 Due metodi della stessa classe aventi lo stesso nome, possono essere distinti in base: 1.Al numero degli argomenti CorpoCeleste( ) CorpoCeleste(char * nome, float mass, float x, float y) 2.Al tipo degli argomenti calcolaPosizione(float fx,float dt); calcolaPosizione(TwoVector f, float dt); 3.[ ovviamente: al tipo e al numero degli argomenti] calcolaPosizione(float fx, float fy, float dt); calcolaPosizione(TwoVector f, float dt); Non e possibile distinguere tra metodi in base al tipo del metodo (void, int, double, …) Overloading dei metodi

32 Operatori aritmetici in C++ AddizioneX+Y SottrazioneX-Y MoltiplicazioneX*Y DivisioneX/Y ModuloX%Y Addizione unaria+X Sottrazione unaria-X Preincremento++X PostincrementoX++ Predecremento--X PostdecrementoX-- binari unari NB non ce loperatore elevazione a potenza, si utilizza un metodo con 2 parametri: double pow(double base,double potenza)

33 Operatori sui bit in C++ Right shift dei bitX >> n Left shift dei bitX << n ORX | Y ANDX & Y XORX ^ Y

34 Operatori logici in C++ Test di uguaglianzaX = = Y Test di differenzaX != Y Test di ordinamentoX < Y Test di ordinamentoX > Y Test di ordinamentoX <= Y Test di ordinamentoX >= Y AND logicoX && Y OR logicoX || Y NOT logico!X

35 Operatori di assegnazione in C++ AssegnazioneX =Y Assegnazione con sommaX +=Y Assegnazione con sottrazioneX -=Y Assegnazione con moltiplicazioneX *=Y Assegnazione con divisioneX /=Y Assegnazione con moduloX %=Y Assegnazione con right shift dei bitX >>= n Assegnazione con left shift dei bitX <<=n Assegnazione con ANDX &= Y Assegnazione con ORX |= Y Assegnazione con XORX ^= Y

36 Overloading degli operatori Consente di definire unalgebra allinterno della classe. Tutto ciò che facciamo con un operatore unario potrebbe essere realizzato mediante un metodo membro senza parametri, che si limiti ad agire sulloggetto in esame (this) o con una funzione esterna alla classe che riceva un unico parametro (una reference alloggetto). Tutto ciò che facciamo con un operatore binario potrebbe essere realizzato mediante un metodo membro con un parametro o una funzione esterna a due parametri. Luso degli operatori rende il codice più leggibile e consente uninterpretazione più immediata delle operazioni effettuate. E importante però non stravolgere il significato convenzionale dei simbili utilizzati: non definite una sottrazione scegliendo + come simbolo !

37 Gli operatori definiti allinterno della classe si chiamano operatori membro. Gli operatori definiti in questo modo sono un modo naturale (e compatto) di identificare un metodo (della classe) e come tali possono accedere ai membri privati. Gli operatori membro si applicano ad oggetti di una classe e possono avere come argomento nessun oggetto (operatori unari) un oggetto (operatori binari) a+b a.operator+(b) a=b a.operator=(b) a=b+c a.operator=(b.operator+(c)) Operatori membro

38 class Compl { private: double re; double im ; public: // costruttori Compl() ; Compl(double a) ; Compl(double a, double b) ; Compl(Compl & c) ; ~Compl() ;//distruttore //metodi di tipo Set void set_Re(double a); void set_Im(double b); //metodi di tipo Get double const Real() ; double const Imm() ; //operatori unari Compl & operator- (); //operatori binari Compl & operator= (Compl const & c); Compl operator+ (Compl const & c); } ; Un esempio classico: la classe dei numeri complessi

39 Compl c1(2,3),c2(1,2),c3; c3 = c1 + c2; // equivalente a c3.operator=(c1.operator+(c2)) double a = 5; c3 = c1 + a; // Ma non posso scrivere c3 = a + c1 conversioni tra tipi Loperatore Compl operator+ (Compl const & c); somma alloggetto this il numero complesso c e ritorna il numero complesso risultante, consentendo operazioni del tipo Come posso fare per sommare oggetti complessi e oggetti reali tra loro? Prevedo lopportuno operatore membro Compl operator+ (doubl const & a);

40 Posso ricorrere ad un operatore non membro a due argomenti Compl operator+(Compl const & c1, Compl const &c2); Che viene dichiarato dopo la chiusura della dichiarazione della classe e che non ha accesso ai membri privati della classe (dovrà usare metodi di tipo get). Posso quindi implementare operatori specifici Compl operator+(Compl const & c1, double const &a); Compl operator+(double const & a, Compl const &c2); O far uso del costruttore Compl(double a) che consente di scrivere double a = 5; compl c=a; Funzioni a due argomenti

41 Loverloading degli operatori > (cin) avviene con funzioni non membro. Gli operatori ostream & operator << (ostream & fstream, const Compl & c); istream & operator >> (istream & fstream, const Compl & c); Sono definiti fuori della definizione della classe overloading delloperatore > (cin)

42 Per referenza o per valore? 1.Negli argomenti delle funzioni, dei metodi e degli operatori è sempre preferibile usare il passaggio per referenza (usando & o il puntatore) poichè si evita la duplicazione delloggetto e si rende quindi il programma più veloce 2.Nella variabile restituita dalla funzione : se la funzione ritorna un oggetto vuol dire che il compilatore vi fornisce una copia di un oggetto costruito allinterno della funzione. Non è possibile ritornare lindirizzo ad un oggetto locale costruito staticamente, si possono invece ritornare indirizzi di oggetti creati dinamicamente (ma ricordarsi sempre che qualcuno dovra cancellarli…). Usate la restituzione di un indirizzo solo quando è strettamente necessario. In particolare è necessario farlo nelloverloading di operatori predefiniti che ritornano indirizzi (ad esempio =, +=, <<) per mantenere la stesse funzionalità.

43 // Questo file e' stato ottenuto modificando, // per scopo didattico, il file originario // ThreVector.h (e ThreeVector.icc) // della libreria CLHEP // =========================================== // This file is a part of the CLHEP - a Class // Library for High Energy Physics. //.SS Authors Leif Lonnblad and Anders Nilsson. // ============================================ #ifndef TWOVECTOR_H #define TWOVECTOR_H #include class TwoVector { private: double dx, dy; // The components. public: // COSTRUTTORE TwoVector( float x, float y ); // COSTRUTTORE PER COPIA TwoVector(const TwoVector &); // DISTRUTTORE ~TwoVector(); TwoVector.h

44 // METODI float x() const; float y() const; // The components in cartesian // coordinate system. void setX(float); void setY(float); // Set the components in // cartesian coordinate system. float phi() const; // The polar angle. float mag2() const; // The magnitude squared (rho^2 // in spherical coordinate system). float mag() const; // The magnitude (rho in spherical // coordinate system). void setPhi(float); // Set phi keeping mag constant (BaBar). void setMag(float); // Set magnitude keeping phi constant // (BaBar).

45 // OPERATORI TwoVector & operator = (const TwoVector &); // Assignment X = Y // BOOLEANI ( Comparisons ) bool operator == (const TwoVector &) const; bool operator != (const TwoVector &) const; TwoVector operator - () const; // Unary minus. TwoVector & operator += (const TwoVector &); // Addition ( += ). TwoVector & operator -= (const TwoVector &); // Subtraction (-= ). TwoVector & operator *= (float); // Scaling with real numbers. double dot(const TwoVector &) const; // Scalar product.

46 TwoVector operator + (const TwoVector &); // Addition of 2-vectors. TwoVector operator – (const TwoVector &); // Subtraction of 2-vectors. double operator * (const TwoVector &); // Scalar product of 2-vectors. // Si potrebbe anche definire un operatore // di moltiplicazione per una // matrice, che definisce una rotazione // generica. // Nel nostro caso lo evitiamo, poiche' // non sono state introdotte le matrici // TwoVector & operator *= (const HepRotation &); // TwoVector & transform (const HepRotation &); // Transformation with a // Rotation matrix. };

47 // dopo il segno }; che indica la fine // della dichiarazione della classe TwoVector operator * (const TwoVector &, float ); TwoVector operator * (float, const TwoVector & ); // Overloading dell'operatore << (cout) // ostream & operator << (ostream &, const TwoVector &); // Output to a stream. #include TwoVector.icc #endif //TWOVECTOR_H

48 // Questo file e' stato ottenuto modificando, // per scopo didattico, il file // originario // ThreVector.icc (e ThreeVector.h) della // libreria CLHEP // ===================== // This file is a part of the CLHEP – // a Class Library for High Energy Physics. // This is the definitions of the // member functions of the // TwoVector class. // ===================== TwoVector::TwoVector(float x, float y) : dx(x), dy(y) {} float TwoVector::x() const { return dx; } Float TwoVector::y() const { return dy; } void TwoVector::setX(Float x) { dx = x; } void TwoVector::setY(Float y) { dy = y; } TwoVector.icc

49 TwoVector::TwoVector(const TwoVector & p) : dx(p.x()), dy(p.y())) {} TwoVector::~TwoVector() {} TwoVector & TwoVector::operator = (const TwoVector & p) { dx = p.x(); dy = p.y(); return *this; } bool TwoVector::operator == (const TwoVector& v) const { return (v.x()==x() && v.y()==y()) ? true : false; } bool TwoVector::operator != (const TwoVector& v) const { return (v.x()!=x() || v.y()!=y()) ? true : false; } TwoVector TwoVector::operator - () const { return TwoVector(-dx, -dy); } TwoVector & TwoVector::operator += (const TwoVector & p) { dx += p.x(); dy += p.y(); return *this; }

50 TwoVector & TwoVector::operator -= (const TwoVector & p) { dx -= p.x(); dy -= p.y(); return *this; } TwoVector & TwoVector::operator *= (float a) { dx *= a; dy *= a; return *this; } float TwoVector::dot(const TwoVector & p) const { return dx*p.x() + dy*p.y(); } float TwoVector::mag2() const { return dx*dx + dy*dy; } float TwoVector::mag() const { return sqrt(mag2()); } float TwoVector::phi() const { return dx == 0.0 && dy == 0.0 ? 0.0 : atan2(dy,dx); }

51 void TwoVector::setMag(float ma){ float ph = phi(); setX(ma* cos(ph)); setY(ma* sin(ph)); } void TwoVector::setPhi(float ph){ float ma = mag(); setX(ma*cos(ph)); setY(ma*sin(ph)); } TwoVector TwoVector::operator + (const TwoVector & a) { return TwoVector(dx + a.x(), dy + a.y()); } TwoVector TwoVector::operator - (const TwoVector & a) { return TwoVector(dx - a.x(), dy - a.y()); } double TwoVector::operator * (const TwoVector & a) { return this->dot(a); }

52 TwoVector operator * (const TwoVector & p, float a) { return TwoVector(a*p.x(), a*p.y()); } TwoVector operator * (float a, const TwoVector & p) { return TwoVector(a*p.x(), a*p.y()); } ostream & operator << (ostream & fstream, const TwoVector & v) { fstream << " (" << v.x() << "," << v.y() << ") "; } non-member operators