1 laboratorio di calcolo II AA 2003/04 terza settimana a cura di Domizia Orestano Dipartimento di Fisica Stanza tel. ( ) UNIVERSITA DEGLI STUDI ROMA TRE DIPARTIMENTO DI FISICA E. AMALDI
2 Loperatore & reference float x = 2.5; float& a = x; float &b = x ; a e b sono chiamati reference e sono due etichette equivalenti alletichetta 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 lindirizzo di i
3 # include 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 550xbffffa34 0xbffffa340x8049a xbffffa34 0xbffffa340x8049a80 Uso di & reference (I)
4 # include 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 550xbffffa34 0xbffffa340x8049a xbffffa34 0xbffffa340x8049a80 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 = 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 dellesercitazione 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 ????????? pianeti int 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 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.cc Prima parte
19 void SistemaSolare::evolvi(float T, float dt) { float t = 0 ; //tempo dallinizio 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.cc Seconda 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 lif su d!=0 } // termina il loop sul j-esimo pianeta // ora conosco la forza che agisce sul- // li-esimo pianeta e posso invocare // calcolaPosizione sulli-esimo pianeta pianeti[i]->calcolaPosizione((float)fx, (float)fy, dt); pianeti[i]->stampaPosizione(); } // termina il loop sulliesimo pianeta cout << endl; t += dt; // viene incrementato il tempo } // while ripeti fino a che t<=T } // limplementazione del metodo evolvi e conclusa SistemaSolare.cc Terza 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., ); // 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