1 laboratorio di calcolo II AA 2003/04 quinta settimana a cura di Domizia Orestano Dipartimento di...

52
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 orestano@fis.uniroma3.it UNIVERSITA’ DEGLI STUDI ROMA TRE DIPARTIMENTO DI FISICA “E. AMALDI”

Transcript of 1 laboratorio di calcolo II AA 2003/04 quinta settimana a cura di Domizia Orestano Dipartimento di...

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

1

laboratorio di calcolo IIAA 2003/04

quinta settimana

a cura di

Domizia Orestano

Dipartimento di FisicaStanza 159 - tel. (06 5517) 7281

www.fis.uniroma3.it/[email protected]

UNIVERSITA’ DEGLI STUDI ROMA TRE

DIPARTIMENTO DI FISICA “E. AMALDI”

Page 2: 1 laboratorio di calcolo II AA 2003/04 quinta settimana a cura di Domizia Orestano Dipartimento di Fisica Stanza 159 - tel. (06 5517) 7281 orestano.

2

sommario

Ripasso degli argomenti trattati la settimana scorsa:ereditarietà, protezioni, polimorfismo e metodi virtuali, distruttori e distruttori virtuali, cosa abbiamo osservato nell’esercitazione

Un altro esempio che illustra nuovamenteereditarietà, polimorfismo e metodi virtuali, distruttori e distruttori virtuali, classi astratte

Overloading Dei metodi e degli operatori, esempi

Page 3: 1 laboratorio di calcolo II AA 2003/04 quinta settimana a cura di Domizia Orestano Dipartimento di Fisica Stanza 159 - tel. (06 5517) 7281 orestano.

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

Page 4: 1 laboratorio di calcolo II AA 2003/04 quinta settimana a cura di Domizia Orestano Dipartimento di Fisica Stanza 159 - tel. (06 5517) 7281 orestano.

4

PrivatiPrivatiPrivati private

PrivatiProtettiProtetti protected

PrivatiProtettiPubblici public

Attributi e Metodi Privati

Attributi e Metodi Protetti

Attributi e Metodi Pubblici

Tipo di Ereditarieta’

ProtezioniAffinché la classe derivata possa accedere agli attributi dellaclasse base, senza violare l’incapsulamento 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à:

Page 5: 1 laboratorio di calcolo II AA 2003/04 quinta settimana a cura di Domizia Orestano Dipartimento di Fisica Stanza 159 - tel. (06 5517) 7281 orestano.

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

Page 6: 1 laboratorio di calcolo II AA 2003/04 quinta settimana a cura di Domizia Orestano Dipartimento di Fisica Stanza 159 - tel. (06 5517) 7281 orestano.

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

Page 7: 1 laboratorio di calcolo II AA 2003/04 quinta settimana a cura di Domizia Orestano Dipartimento di Fisica Stanza 159 - tel. (06 5517) 7281 orestano.

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 è statosufficiente instanziarli nel main e dichiararli con aggiungiPianeta alla classe SistemaSolare, non sono state necessarie modifiche a SistemaSolare.

Page 8: 1 laboratorio di calcolo II AA 2003/04 quinta settimana a cura di Domizia Orestano Dipartimento di Fisica Stanza 159 - tel. (06 5517) 7281 orestano.

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

Page 9: 1 laboratorio di calcolo II AA 2003/04 quinta settimana a cura di Domizia Orestano Dipartimento di Fisica Stanza 159 - tel. (06 5517) 7281 orestano.

9

#include "Sonda.h"

#include <iostream.h>

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

Page 10: 1 laboratorio di calcolo II AA 2003/04 quinta settimana a cura di Domizia Orestano Dipartimento di Fisica Stanza 159 - tel. (06 5517) 7281 orestano.

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

Page 11: 1 laboratorio di calcolo II AA 2003/04 quinta settimana a cura di Domizia Orestano Dipartimento di Fisica Stanza 159 - tel. (06 5517) 7281 orestano.

11

#include “SistemaSolare.h”

#include “Sonda.h”

int main() {

SistemaSolare ss(3) ; // definisci un SistemaSolare

// definisci due pianeti

CorpoCeleste sole(“Il Sole”, 1.98e30, 0., 0., 0., 0.) ;

CorpoCeleste terra(“La Terra”, 5.98e24, 1.52e11, 0., 0., 29476.35) ;

// definisci una sonda

Sonda voyager(“Voyager II”, 110000., 100., &terra, 38000., -10800.) ;

// aggiungi i pianeti e la sonda al sistema solare

ss.aggiungiPianeta(&sole) ;

ss.aggiungiPianeta(&terra) ;

ss.aggiungiPianeta(&voyager) ;

// fai evolvere il sistema per 365 giorni

ss.evolvi(86400*365, 86400) ;

return 0 ;

}

simula.cc

Page 12: 1 laboratorio di calcolo II AA 2003/04 quinta settimana a cura di Domizia Orestano Dipartimento di Fisica Stanza 159 - tel. (06 5517) 7281 orestano.

12

Alcune modifiche sono state invece apportate in CorpoCeleste.h:

• dichiarazione gli attributi protected anziché privatechi 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::calcolaPosizionealtrimenti, in SistemaSolare::evolvi, l’istruzionepianeti[i]->calcolaPosizione((float)fx, (float)fy, dt);chiamerebbe sempre CorpoCeleste::calcolaPosizione, anche per i puntatori ad oggetti Sonda

• dichiazione come virtual del metodo CorpoCeleste::~CorpoCelesteper 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!

Page 13: 1 laboratorio di calcolo II AA 2003/04 quinta settimana a cura di Domizia Orestano Dipartimento di Fisica Stanza 159 - tel. (06 5517) 7281 orestano.

13

#ifndef CORPOCELESTE_H#define CORPOCELESTE_Hclass 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à

Page 14: 1 laboratorio di calcolo II AA 2003/04 quinta settimana a cura di Domizia Orestano Dipartimento di Fisica Stanza 159 - tel. (06 5517) 7281 orestano.

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

Page 15: 1 laboratorio di calcolo II AA 2003/04 quinta settimana a cura di Domizia Orestano Dipartimento di Fisica Stanza 159 - tel. (06 5517) 7281 orestano.

15

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

shape

cerchio quadrato

Un altro esempio

Page 16: 1 laboratorio di calcolo II AA 2003/04 quinta settimana a cura di Domizia Orestano Dipartimento di Fisica Stanza 159 - tel. (06 5517) 7281 orestano.

16

#ifndef SHAPE_H#define SHAPE_H

#include <iostream.h>

class shape {

public: shape() {}; ~shape() { cout << " Distruggo una shape " << endl << endl ; };

void print() { cout << " Sono una shape" << endl ; };

};

#endif

shape.h

Page 17: 1 laboratorio di calcolo II AA 2003/04 quinta settimana a cura di Domizia Orestano Dipartimento di Fisica Stanza 159 - tel. (06 5517) 7281 orestano.

17

#ifndef CERCHIO_H#define CERCHIO_H

#include <iostream.h>#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

Page 18: 1 laboratorio di calcolo II AA 2003/04 quinta settimana a cura di Domizia Orestano Dipartimento di Fisica Stanza 159 - tel. (06 5517) 7281 orestano.

18

#ifndef QUADRATO_H#define QUADRATO_H

#include <iostream.h>#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

Page 19: 1 laboratorio di calcolo II AA 2003/04 quinta settimana a cura di Domizia Orestano Dipartimento di Fisica Stanza 159 - tel. (06 5517) 7281 orestano.

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 una shape Sono una shape

Sono una shape Sono un cerchio Sono un quadrato

Senza virtual

Page 20: 1 laboratorio di calcolo II AA 2003/04 quinta settimana a cura di Domizia Orestano Dipartimento di Fisica Stanza 159 - tel. (06 5517) 7281 orestano.

20

#ifndef SHAPE_H#define SHAPE_H

#include <iostream.h>

class shape {

public: shape() {}; ~shape() { cout << " Distruggo una shape " << endl << endl ; };

void print() { cout << " Sono una shape" << endl ; };

};

#endif

shape.h

virtual

Page 21: 1 laboratorio di calcolo II AA 2003/04 quinta settimana a cura di Domizia Orestano Dipartimento di Fisica Stanza 159 - tel. (06 5517) 7281 orestano.

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

Page 22: 1 laboratorio di calcolo II AA 2003/04 quinta settimana a cura di Domizia Orestano Dipartimento di Fisica Stanza 159 - tel. (06 5517) 7281 orestano.

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

Distruggo una shape

========================== Applico delete shape 0 : Distruggo una shape

shape 1 : Distruggo una shape

shape 2 : Distruggo una shape =========================

Page 23: 1 laboratorio di calcolo II AA 2003/04 quinta settimana a cura di Domizia Orestano Dipartimento di Fisica Stanza 159 - tel. (06 5517) 7281 orestano.

23

#ifndef SHAPE_H#define SHAPE_H

#include <iostream.h>

class shape {

public: shape() {}; ~shape() { cout << " Distruggo una shape " << endl << endl ; };

void print() { cout << " Sono una shape" << endl ; };

};

#endif

shape.h

virtual

virtual

Page 24: 1 laboratorio di calcolo II AA 2003/04 quinta settimana a cura di Domizia Orestano Dipartimento di Fisica Stanza 159 - tel. (06 5517) 7281 orestano.

24

Con distruttore virtualint 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

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 =========================

Page 25: 1 laboratorio di calcolo II AA 2003/04 quinta settimana a cura di Domizia Orestano Dipartimento di Fisica Stanza 159 - tel. (06 5517) 7281 orestano.

25

Supponiamo ora di voler aggiungere alle classi geometriche un metodo che determini l’area della figura.

L’area 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 ;

Page 26: 1 laboratorio di calcolo II AA 2003/04 quinta settimana a cura di Domizia Orestano Dipartimento di Fisica Stanza 159 - tel. (06 5517) 7281 orestano.

26

#ifndef SHAPE_H#define SHAPE_H

#include <iostream.h>

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

Page 27: 1 laboratorio di calcolo II AA 2003/04 quinta settimana a cura di Domizia Orestano Dipartimento di Fisica Stanza 159 - tel. (06 5517) 7281 orestano.

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 Area2. Gli oggetti di tipo shape non possono essere istanziati per lo

stessso motivo

Rimosso dal main l’oggetto di tipo shape aggiungiamo il metodo Area nelle classi derivate:

Page 28: 1 laboratorio di calcolo II AA 2003/04 quinta settimana a cura di Domizia Orestano Dipartimento di Fisica Stanza 159 - tel. (06 5517) 7281 orestano.

28

#ifndef CERCHIO_H#define CERCHIO_H

#include <iostream.h>#include ”shape.h“#include <math.h>

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

Page 29: 1 laboratorio di calcolo II AA 2003/04 quinta settimana a cura di Domizia Orestano Dipartimento di Fisica Stanza 159 - tel. (06 5517) 7281 orestano.

29

#ifndef QUADRATO_H#define QUADRATO_H

#include <iostream.h>#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

Page 30: 1 laboratorio di calcolo II AA 2003/04 quinta settimana a cura di Domizia Orestano Dipartimento di Fisica Stanza 159 - tel. (06 5517) 7281 orestano.

30

int main() {

shape * v[2]; v[0] = new circle(1); v[1] = new quadrato(1);

cout << endl; v[0]->print(); cout << v[0]->Area() <<endl; v[1]->print(); cout << v[1]->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;};

Page 31: 1 laboratorio di calcolo II AA 2003/04 quinta settimana a cura di Domizia Orestano Dipartimento di Fisica Stanza 159 - tel. (06 5517) 7281 orestano.

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

Page 32: 1 laboratorio di calcolo II AA 2003/04 quinta settimana a cura di Domizia Orestano Dipartimento di Fisica Stanza 159 - tel. (06 5517) 7281 orestano.

32

Operatori aritmetici in C++Addizione X+Y

Sottrazione X-Y

Moltiplicazione X*Y

Divisione X/Y

Modulo X%Y

Addizione unaria +X

Sottrazione unaria -X

Preincremento ++X

Postincremento X++

Predecremento --X

Postdecremento X--

bina

riun

ari

NB non c’e’ l’operatore elevazione a potenza, si utilizza un metodo con 2 parametri: double pow(double base,double potenza)

Page 33: 1 laboratorio di calcolo II AA 2003/04 quinta settimana a cura di Domizia Orestano Dipartimento di Fisica Stanza 159 - tel. (06 5517) 7281 orestano.

33

Operatori sui bit in C++

Right shift dei bit X >> n

Left shift dei bit X << n

OR X | Y

AND X & Y

XOR X ^ Y

Page 34: 1 laboratorio di calcolo II AA 2003/04 quinta settimana a cura di Domizia Orestano Dipartimento di Fisica Stanza 159 - tel. (06 5517) 7281 orestano.

34

Operatori logici in C++

Test di uguaglianza X = = Y

Test di differenza X != Y

Test di ordinamento X < Y

Test di ordinamento X > Y

Test di ordinamento X <= Y

Test di ordinamento X >= Y

AND logico X && Y

OR logico X || Y

NOT logico !X

Page 35: 1 laboratorio di calcolo II AA 2003/04 quinta settimana a cura di Domizia Orestano Dipartimento di Fisica Stanza 159 - tel. (06 5517) 7281 orestano.

35

Operatori di assegnazione in C++

Assegnazione X =Y

Assegnazione con somma X +=Y

Assegnazione con sottrazione X -=Y

Assegnazione con moltiplicazione X *=Y

Assegnazione con divisione X /=Y

Assegnazione con modulo X %=Y

Assegnazione con right shift dei bit X >>= n

Assegnazione con left shift dei bit X <<=n

Assegnazione con AND X &= Y

Assegnazione con OR X |= Y

Assegnazione con XOR X ^= Y

Page 36: 1 laboratorio di calcolo II AA 2003/04 quinta settimana a cura di Domizia Orestano Dipartimento di Fisica Stanza 159 - tel. (06 5517) 7281 orestano.

36

Overloading degli operatoriConsente di definire un’algebra all’interno della classe.

Tutto ciò che facciamo con un operatore unario potrebbe essere realizzato mediante un metodo membro senza parametri, che si limiti ad agire sull’oggetto in esame (this) o con una funzione esterna alla classe che riceva un unico parametro (una reference all’oggetto).

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.

L’uso degli operatori rende il codice più leggibile e consente un’interpretazione più immediata delle operazioni effettuate. E’ importante però non stravolgere il significato convenzionale dei simbili utilizzati: non definite una sottrazione scegliendo + come simbolo !

Page 37: 1 laboratorio di calcolo II AA 2003/04 quinta settimana a cura di Domizia Orestano Dipartimento di Fisica Stanza 159 - tel. (06 5517) 7281 orestano.

37

Gli operatori definiti all’interno 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

Page 38: 1 laboratorio di calcolo II AA 2003/04 quinta settimana a cura di Domizia Orestano Dipartimento di Fisica Stanza 159 - tel. (06 5517) 7281 orestano.

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 Setvoid set_Re(double a);

void set_Im(double b);

//metodi di tipo Getdouble 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

Page 39: 1 laboratorio di calcolo II AA 2003/04 quinta settimana a cura di Domizia Orestano Dipartimento di Fisica Stanza 159 - tel. (06 5517) 7281 orestano.

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 tipiL’operatore

Compl operator+ (Compl const & c);somma all’oggetto 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 l’opportuno operatore membro

Compl operator+ (doubl const & a);

Page 40: 1 laboratorio di calcolo II AA 2003/04 quinta settimana a cura di Domizia Orestano Dipartimento di Fisica Stanza 159 - tel. (06 5517) 7281 orestano.

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

Page 41: 1 laboratorio di calcolo II AA 2003/04 quinta settimana a cura di Domizia Orestano Dipartimento di Fisica Stanza 159 - tel. (06 5517) 7281 orestano.

41

L’overloading degli operatori << (cout) e >> (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 dell’operatore << (cout)overloading dell’operatore >> (cin)

Page 42: 1 laboratorio di calcolo II AA 2003/04 quinta settimana a cura di Domizia Orestano Dipartimento di Fisica Stanza 159 - tel. (06 5517) 7281 orestano.

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 dell’oggetto 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 all’interno della funzione. Non è possibile ritornare l’indirizzo 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 nell’overloading di operatori predefiniti che ritornano indirizzi (ad esempio =, += , <<) per mantenere la stesse funzionalità.

Page 43: 1 laboratorio di calcolo II AA 2003/04 quinta settimana a cura di Domizia Orestano Dipartimento di Fisica Stanza 159 - tel. (06 5517) 7281 orestano.

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 <iostream.h>#include <math.h> 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

Page 44: 1 laboratorio di calcolo II AA 2003/04 quinta settimana a cura di Domizia Orestano Dipartimento di Fisica Stanza 159 - tel. (06 5517) 7281 orestano.

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

Page 45: 1 laboratorio di calcolo II AA 2003/04 quinta settimana a cura di Domizia Orestano Dipartimento di Fisica Stanza 159 - tel. (06 5517) 7281 orestano.

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.

Page 46: 1 laboratorio di calcolo II AA 2003/04 quinta settimana a cura di Domizia Orestano Dipartimento di Fisica Stanza 159 - tel. (06 5517) 7281 orestano.

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.

};

Page 47: 1 laboratorio di calcolo II AA 2003/04 quinta settimana a cura di Domizia Orestano Dipartimento di Fisica Stanza 159 - tel. (06 5517) 7281 orestano.

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

Page 48: 1 laboratorio di calcolo II AA 2003/04 quinta settimana a cura di Domizia Orestano Dipartimento di Fisica Stanza 159 - tel. (06 5517) 7281 orestano.

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

Page 49: 1 laboratorio di calcolo II AA 2003/04 quinta settimana a cura di Domizia Orestano Dipartimento di Fisica Stanza 159 - tel. (06 5517) 7281 orestano.

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; }

Page 50: 1 laboratorio di calcolo II AA 2003/04 quinta settimana a cura di Domizia Orestano Dipartimento di Fisica Stanza 159 - tel. (06 5517) 7281 orestano.

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

Page 51: 1 laboratorio di calcolo II AA 2003/04 quinta settimana a cura di Domizia Orestano Dipartimento di Fisica Stanza 159 - tel. (06 5517) 7281 orestano.

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

Page 52: 1 laboratorio di calcolo II AA 2003/04 quinta settimana a cura di Domizia Orestano Dipartimento di Fisica Stanza 159 - tel. (06 5517) 7281 orestano.

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