UNIVERSITA’ DEGLI STUDI ROMA TRE
DIPARTIMENTO DI FISICA “E. AMALDI”
laboratorio di calcolo II
AA 2003/04
terza settimana
a cura di
Domizia Orestano
Dipartimento di Fisica
Stanza 159 - tel. (06 5517) 7281
www.fis.uniroma3.it/~orestano
[email protected]
1
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
2
Uso di & reference (I)
# 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
3
Uso di & reference (II)
# 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
4
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
5
Passaggio dei parametri ad una funzione (II)
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;
}
6
Passaggio dei parametri ad una funzione (III)
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;
}
7
Passaggio dei parametri ad una funzione (IV)
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;
}
8
Passaggio dei parametri ad una funzione (V)
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
9
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);
10
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
11
relazione di
aggregazione
12
La classe SistemaSolare
SistemaSolare
????????? pianeti
int N
SistemaSolare(int n)
~SistemaSolare()
int aggiungiPianeta(CorpoCeleste * unPianeta)
void evolvi(float T, float dt)
int nPianeti()
13
#include "CorpoCeleste.h"
#define G 6.673e-11
SistemaSolare.h
class SistemaSolare {
protected:
??????????
pianeti;
int N;
// lista dei pianeti
// numero dei pianeti
public:
SistemaSolare(int n);
~SistemaSolare();
int aggiungiPianeta(CorpoCeleste *unPianeta);
int nPianeti() {return N;};
void evolvi(float T, float dt);
};
14
15
16
#include "CorpoCeleste.h"
#define G 6.673e-11
SistemaSolare.h
class SistemaSolare {
protected:
CorpoCeleste **
pianeti;
int N;
// lista dei pianeti
// numero dei pianeti
public:
SistemaSolare(int n);
~SistemaSolare();
int aggiungiPianeta(CorpoCeleste *unPianeta);
int nPianeti() {return N;};
void evolvi(float T, float dt);
};
17
#include
#include
#include
#include
"SistemaSolare.h"
<stdlib.h>
<math.h>
<iostream.h>
SistemaSolare.cc
Prima parte
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;
}
18
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++) {
SistemaSolare.cc
Seconda parte
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())
);
19
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
SistemaSolare.cc
// ora conosco la forza che agisce sulTerza parte
// 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
20
Interaction Diagram (semplificato)
21
#include “SistemaSolare.h”
simula.cc
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;
}
22
Scarica

ppt - Università degli Studi Roma Tre