1
laboratorio di calcolo IIAA 2003/04
terza 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”
2
L’operatore & reference
float x = 2.5;
float& a = x;
float &b = x ;
a e b sono chiamati reference e sono due “etichette” equivalenti all’etichetta x, che fanno riferimento allo stesso oggetto.
Non confondere reference con puntatore:
int i = 3; // oggetto i
int &j = i; // reference a i
int *p = &i; // puntatore a i
i ha un indirizzo in memoria che contiene il valore 3
j ha lo stesso indirizzo
p contiene l’indirizzo di i
3
# include <iostream.h> int main() { int i=5; int *p; int *q; p = &i; q = new int(i); cout << i << " " << *p << " " << *q << " " << &i << " " << p << " " << q << endl; i=8; cout << i << " " << *p << " " << *q << " " << &i << " " << p << " " << q << endl; return 0; }
5 5 5 0xbffffa34 0xbffffa34 0x8049a80
8 8 5 0xbffffa34 0xbffffa34 0x8049a80
Uso di & reference (I)
4
# include <iostream.h> int main() { int i=5; int &j=i; int *q; q = new int(i); cout << i << " " << j << " " << *q << " " << &i << " " << &j << " " << q << endl; i=8; cout << i << " " << j << " " << *q << " " << &i << " " << &j << " " << q << endl; return 0; }
5 5 5 0xbffffa34 0xbffffa34 0x8049a80
8 8 5 0xbffffa34 0xbffffa34 0x8049a80
Uso di & reference (II)
5
Passaggio dei parametri ad una funzione (I)
I parametri di una funzione possono essere trasmessi per valore:
void swap_value(int i1, int i2); // prototipo di una funzione che riceve due parametri per valore
o per reference:
void swap_ref(int &i1, int &i2); // prototipo di una funzione che riceve due parametri per reference
6
Per valore:
void swap_value(int i1,int i2) {
// quando viene chiamata questa funzione con una // istruzione del tipo// swap(a,b);// tutto va come se il compilatore eseguisse le istruzioni// int i1=a;// int i2=b;
int temp = i1;
i1 = i2;
i2 = temp;
}
Passaggio dei parametri ad una funzione (II)
7
Per reference:
void swap_ref(int &i1,int &i2) {
// quando viene chiamata questa funzione con una
// istruzione del tipo// swap(a,b);// tutto va come se il compilatore eseguisse le istruzioni// int &i1=a;// int &i2=b;
int temp = i1;
i1 = i2;
i2 = temp;
}
Passaggio dei parametri ad una funzione (III)
8
con i puntatori (“alla maniera del C”):
void swap_point(int *i1,int *i2) {
// quando viene chiamata questa funzione con una
// istruzione del tipo// swap(&a,&b);// tutto va come se il compilatore eseguisse le istruzioni// int *i1=&a;// int *i2=&b;
int temp = *i1;
*i1 = *i2;
*i2 = temp;
}
Passaggio dei parametri ad una funzione (IV)
9
int main() { int a = 2; int b = 3; cout << endl; cout << endl << " a = " << a << "; b = " << b << endl ; swap_value(a,b); cout << endl << " a = " << a << "; b = " << b << endl ; swap_ref(a,b); cout << endl << " a = " << a << "; b = " << b << endl ; swap_point(&a,&b); cout << endl << " a = " << a << "; b = " << b << endl ;
return 0; }
a = 2; b = 3
a = 2; b = 3
a = 3; b = 2
a = 2; b = 3
Passaggio dei parametri ad una funzione (V)
10
Passaggio dei parametri ad una funzione (VI)
Funzioni che hanno come parametro un vettore:
void modulo2(double * vect, int dim) {double mod = 0;
for(int I=0; I<dim; I++){
mod += vect[I]*vect[I]; // uso vect[I]
vect[I] = 0; // modifico vect[I]
}
return mod;
}Un vettore viene identificato mediante il puntatore al suo primo elemento, quindi la funzione riceve sempre un puntatore e potrebbe andare ad alterare il contenuto del vettore... Come si realizza in questo caso il passaggio per valore? Cambiando il prototipo della funzione in:
void modulo2(const double * vect, int dim);
11
Stato della simulazione del sistema solare
• Abbiamo creato la classe Corpo Celeste
• Abbiamo scritto diverse versioni del programma main che instanzia direttamente degli oggetti di questa classe
• Prima di proseguire sarà bene soffermarsi a verificare la correttezza del codice prodotto: nel corso dell’esercitazione effetturete un esercizio di “debug” del metodo CorpoCeleste::CalcolaPosizione
• Ora torniamo al diagramma UML delle classi previste e effettuiamo la dichiarazione della classe SistemaSolare e la sua implementazione
• Infine scriviamo il programma principale, simula.cc
12
relazione di aggregazione
13
La classe SistemaSolare
SistemaSolare
????????? pianetiint N
SistemaSolare(int n)
~SistemaSolare()
int aggiungiPianeta(CorpoCeleste * unPianeta)
void evolvi(float T, float dt)
int nPianeti()
14
#include "CorpoCeleste.h"
#define G 6.673e-11
class SistemaSolare {
protected:
?????????? pianeti; // lista dei pianeti
int N; // numero dei pianeti
public:
SistemaSolare(int n);
~SistemaSolare();
int aggiungiPianeta(CorpoCeleste *unPianeta);
int nPianeti() {return N;};
void evolvi(float T, float dt);
};
SistemaSolare.h
15
16
17
#include "CorpoCeleste.h"
#define G 6.673e-11
class SistemaSolare {
protected:
CorpoCeleste ** pianeti; // lista dei pianeti
int N; // numero dei pianeti
public:
SistemaSolare(int n);
~SistemaSolare();
int aggiungiPianeta(CorpoCeleste *unPianeta);
int nPianeti() {return N;};
void evolvi(float T, float dt);
};
SistemaSolare.h
18
#include "SistemaSolare.h" #include <stdlib.h>#include <math.h>#include <iostream.h> SistemaSolare::SistemaSolare(int n) {
pianeti = new CorpoCeleste*[n]; // si alloca un vettore di puntatori a oggetti di tipo // CorpoCeleste: n puntatori a CorpoCeleste N = 0; // si pone il numero iniziale di pianeti pari a 0} SistemaSolare::~SistemaSolare() { delete [] pianeti;} int SistemaSolare::aggiungiPianeta(CorpoCeleste *unPianeta) {
pianeti[N++] = unPianeta; // si aggiunge unPianeta
//alla lista dei pianeti e si incrementa N di uno.
return N;}
SistemaSolare.ccPrima parte
19
void SistemaSolare::evolvi(float T, float dt) {
float t = 0 ; //tempo dall’inizio della simulazione
// ripeti fino a che t<=T while (t <= T) {
// loop sui pianeti
for (int i=0; i<N; i++) {
double fx = 0.; double fy = 0.;
// calcola la forza esercitata sul pianeta // i-esimo da parte di tutti gli altri // pianeti j-esimi
for (int j=0; j<N; j++) {
// calcola la distanza tra i e j
double d = sqrt( (pianeti[i]->X()-pianeti[j]->X())* (pianeti[i]->X()-pianeti[j]->X())+
(pianeti[i]->Y()-pianeti[j]->Y())* (pianeti[i]->Y()-pianeti[j]->Y()) );
SistemaSolare.ccSeconda parte
20
if (d!=0) { //Somma a fx e fy agenti sull i-esimo corpo //la forza dovuta al corpo j-esimo
fx += -G*pianeti[i]->M()*pianeti[j]->M()* ( pianeti[i]->X() – pianeti[j]->X() ) / (d*d*d) ;
fy += -G*pianeti[i]->M()*pianeti[j]->M()* ( pianeti[i]->Y() – pianeti[j]->Y()) / (d*d*d) ;
} // termina l’if su d!=0
} // termina il loop sul j-esimo pianeta // ora conosco la forza che agisce sul- // l’i-esimo pianeta e posso invocare // calcolaPosizione sull’i-esimo pianeta pianeti[i]->calcolaPosizione((float)fx, (float)fy, dt); pianeti[i]->stampaPosizione();
} // termina il loop sull’iesimo pianeta
cout << endl; t += dt; // viene incrementato il tempo
} // while ripeti fino a che t<=T} // l’implementazione del metodo evolvi e’ conclusa
SistemaSolare.ccTerza parte
21
Interaction Diagram (semplificato)
22
#include “SistemaSolare.h” int main() { //NB si usano unita’ MKS // instanzio un oggetto SistemaSolare ss con 2 corpi SistemaSolare ss(2);
// instanzio due oggetti CoproCeleste, sole e terra
CorpoCeleste sole(“Il Sole”, 1.98e30, 0., 0., 0., 0.); CorpoCeleste terra(“La Terra”, 5.98e24, 1.52e11, 0., 0., 29476.35);
// li aggiungo al Sistemasolare ss ss.aggiungiPianeta(&sole); ss.aggiungiPianeta(&terra);
// faccio evolvere il sistema per 1 anno in passi di un giorno ss.evolvi(86400*365, 86400);
return 0;}
simula.cc