Vincenzo Innocente - Corso breve OO 1 Introduzione ai linguaggi compilati orientati ad oggetti Alessandra Doria, Napoli Vincenzo Innocente, CERN Luca Lista, Napoli
Vincenzo Innocente - Corso breve OO 2 Programmazione procedurale Uno dei principali problemi del software è la sua evoluzione e la sua manutenzione – specialmente in grossi progetti come un esperimento di HEP Esempi con linguaggi procedurali (Fortran): –Cosa succede quando il codice viene modificato –Dipendenze all’interno del codice
Vincenzo Innocente - Corso breve OO 3 Un esempio semplice Un esempio “elegante”: copiare una sequenza di caratteri dalla tastiera alla stampante SUBROUTINE COPY LOGICAL READKB CHARACTER C DO WHILE (READKB(C)) CALL WRTPRN(C) ENDDO RETURN Questo codice dovrà prima o poi essere modificato (aggiornamenti, estensioni, richieste dagli utenti, ecc.)
Vincenzo Innocente - Corso breve OO 4 Modifiche dei requisiti Una modifica un po’ meno elegante: scrivere anche su un file SUBROUTINE COPY(FLAG) LOGICAL READKB INTEGER FLAG CHARACTER C DO WHILE (READKB(C)) IF (FLAG.EQ. 1) CALL WRTPRN(C) ELSE CALL WRTFL(C) ENDIF ENDDO RETURN
Vincenzo Innocente - Corso breve OO 5 SUBROUTINE COPY(FLAG1, FLAG2) LOGICAL READKB, READFL INTEGER FLAG1, FLAG2 LOGICAL CONT CHARACTER C 10 IF (FLAG1.EQ. 1) THEN CONT = READKB(C) ELSE CONT = READFL(C) ENDIF IF (CONT) THEN IF (FLAG2.EQ. 1) THEN CALL WRTPRN(C) ELSE CALL WRTFL(C) ENDIF GOTO 10 ENDIF RETURN Evoluzione incontrollata Un’altra modifica per niente elegante: leggere anche de un file
Vincenzo Innocente - Corso breve OO 6 Descrizione dei dati Esempio: cinematica relativistica COMMON /MYDATA/ P1(4), P2(4), + P3(4), P4(4) REAL P1(4), P2(4), P3(4), P4(4) COSTHETA12 = (P1(1)*P2(1) + P1(2)*P2(2) + + P1(3)*P2(3))/... COSTHETA13 = (P1(1)*P3(1) + P1(2)*P3(2) + + P1(3)*P3(3))/... COSTHETA14 = (P1(1)*P4(1) + P1(2)*P4(2) + + P1(3)*P4(3))/... FUNCTION COSTHETA(P1, P2) REAL P1(4), P2(4) COSTHETA = (P1(1)*P2(1) + P1(2)*P2(2) + + P1(3)*P2(3))/... END COMMON /MYDATA/ P1(4), P2(4), + P3(4), P4(4) REAL P1(4), P2(4), P3(4), P4(4) COSTHETA12 = COSTHETA(P1, P2) COSTHETA13 = COSTHETA(P1, P3) COSTHETA14 = COSTHETA(P1, P4) Idea: perché non usare una function? Idea: perché non usare una function?
Vincenzo Innocente - Corso breve OO 7 COMMON /MYDATA/ P1(4), P2(4), + P3(4), P4(4) Evoluzione del codice Se cambia il formato del common block? COMMON /MYDATA/ P(4), E(4), + THETA(4), PHI(4) Bisogna cambiare la funzione (gli argomenti sono diversi) COMMON /MYDATA/ P(4), E(4), + THETA(4), PHI(4) COSTHETA12 = COSTHETA1(THETA(1),THETA(2), + PHI(1), PHI(2)) COSTHETA13 = COSTHETA1(THETA(1),THETA(3), + PHI(1), PHI(3)) COSTHETA14 = COSTHETA1(THETA(1),THETA(4), + PHI(1), PHI(4)) FUNCTION COSTHETA1(THETA1, THETA2, + PHI1, PHI2) COSTHETA1 = SIN(THETA1)*SIN(THETA2) * + COS(PHI1-PHI2) + COS(THETA1)*COS(THETA2) END …e il codice!
Vincenzo Innocente - Corso breve OO 8 COMMON /MYDATA/ P1(4), P2(4), + P3(4), P4(4) COSTHETA12 = COSTHETA(P1, P2) COSTHETA13 = COSTHETA(P1, P3) COSTHETA14 = COSTHETA(P1, P4) Il concetto di dipendenza Nell’esempio precedente il codice di analisi (“alto livello”) dipende dai dettagli della struttura dati (“basso livello”). FUNCTION COSTHETA(P1, P2) REAL P1(4), P2(4) COSTHETA = (P1(1)*P2(1) + P1(2)*P2(2) + + P1(3)*P2(3))/... END COSTHETA dipende dalla struttura dei dati P1 e P2 Il codice di analisi dipende dalla struttura del common block MYDATA
Vincenzo Innocente - Corso breve OO 9 C++ /Object Oriented Riduce la dipendenza del codice di alto livello dalla rappresentazione dei dati Permette il riutilizzo del codice di alto livello Nasconde i dettagli di implementazione
Vincenzo Innocente - Corso breve OO 10 PARAMETER (NPLAN = 8, NSTOP = NPLAN-1, + NSTOP5 = 5*NPLAN ) COMMON /GCFIT/ + CSIX(6,0:NSTOP),CSIY(6,0:NSTOP) +,CSIZ(6,0:NSTOP) +,WW(5,5,0:NSTOP),DDT(5,5,0:NSTOP) +,VV(5,5,0:NSTOP),SS(5,5,0:NSTOP) +,CC(5,5,0:NSTOP) +,CHI2,CHI2N,CHI2T,CHI2M +,PLANI(3,4,0:NSTOP) DOUBLE PRECISION + CSIX,CSIY,CSIZ +,WW,DDT +,VV,SS +,CC +,CHI2,CHI2N,CHI2T,CHI2M Kalman.inc SUBROUTINE FILTER(JSTOP,IFAIL) INTEGER JSTOP, IFAIL #include “Kalman.inc” DOUBLE PRECISION YDUM(5) * ** filter * CALL DVADD(25,WW(1,1,JSTOP),WW(2,1,JSTOP), + VV(1,1,JSTOP),VV(2,1,JSTOP), + CC(1,1,JSTOP),CC(2,1,JSTOP)) CALL DSINV(5,CC(1,1,JSTOP),5,IFAIL) IF ( IFAIL.NE.0 ) THEN 1 PRINT *,'DSINV IFAIL',IFAIL,' AT PLANE ',JSTOP CALL VZERO(CC(1,1,JSTOP),50) RETURN ENDIF CALL DMMPY(5,5,VV(1,1,JSTOP),VV(1,2,JSTOP),VV(2,1,JSTOP), + CSIZ(1,JSTOP),CSIZ(2,JSTOP), + YDUM(1), YDUM(2)) CALL DMMPA(5,5,WW(1,1,JSTOP),WW(1,2,JSTOP),WW(2,1,JSTOP), + CSIY(1,JSTOP),CSIY(2,JSTOP), + YDUM(1), YDUM(2)) CALL DMMPY(5,5,CC(1,1,JSTOP),CC(1,2,JSTOP),CC(2,1,JSTOP), + YDUM(1), YDUM(2), + CSIX(1,JSTOP),CSIX(2,JSTOP)) CSIX(6,JSTOP) = CSIY(6,JSTOP) * CHI2 DO J = 1,5 DO K=1,5 CHI2 = CHI2 + + (CSIX(K,JSTOP)-CSIZ(K,JSTOP))*VV(K,J,JSTOP)* + (CSIX(J,JSTOP)-CSIZ(J,JSTOP)) + + (CSIX(K,JSTOP)-CSIY(K,JSTOP))*WW(K,J,JSTOP)* + (CSIX(J,JSTOP)-CSIY(J,JSTOP)) ENDDO * END Filter.f Dati globali Modello dei dati esplicito Sintassi oscura Tipo non controllato
Vincenzo Innocente - Corso breve OO 11 class KalmanStep { public: bool propagate(const KalmanStep& previous); bool filter() ; bool smooth(const KalmanStep& next); private: Vector5 csix; SimMatrix5 cc; SimMatrix5 ss; Vector5 csiy; SimMatrix5 ww; Vector5 csiz; SimMatrix5 vv; Matrix5 ddt; Plane plane; double chi2; }; KalmanStep.h bool KalmanStep::filter() { bool fail = false; cc = ww+vv; cc.invert(fail); if (fail) { cc.zero(); return !fail;} csix = cc*(vv*csiz + ww*csiy); chi2 += (csix-csiz)*vv*(csix-csiz)+ (csix-csiy)*ww*(csix-csiy); return !fail; } KalmanStep.cc Dati incapsulati Modello dei dati nascosto Sintassi “naturale” Tipo controllato o convertito
Vincenzo Innocente - Corso breve OO 12 Classi e oggetti Definizione di nuovi tipi (oltre a int, float, double) come: –numeri complessi, –vettori, –matrici,... ma anche: –tracce, –superfici, –elementi di rivelatori, –cluster,... Gli oggetti permettono di modellare una problema che rappresenti la realtà
Vincenzo Innocente - Corso breve OO 13 Concetti base dell’OO Classi ed oggetti Incapsulamento Relazione di ereditarietà Polimorfismo Programmazione Generica ( C++ )
Vincenzo Innocente - Corso breve OO 14 Classi e Oggetti Un esempio di programma “orientato ad oggetti”: un videogioco
Vincenzo Innocente - Corso breve OO 15 SoldatoSoldatoClienteCliente
Vincenzo Innocente - Corso breve OO 16 F ORTRAN vs C / C++ Sintassi F77 e C a confronto PROGRAM TEST C esempio di programma... END int main() { // esempio di programma... return 0; // fine } INTEGER I INTEGER*4 J REAL X REAL*8 D int i; long j; float x; double d; In C/ C++ non è necessario un particolare formato il codice spazi... Il C/ C++ è case sensitive Istruzioni separate da “ ; ”
Vincenzo Innocente - Corso breve OO 17 F ORTRAN vs C / C++ Controllo di flusso del programma DO I = 1, ENDDO IF (I.EQ.10.AND. J.GT.4.OR. X) THEN... ENDIF DO WHILE(X.NE. 5)... ENDDO for ( i = 1; i <= 10; i++ ) {... } if ( i == 10 && j > 4 || x ) {... } while( x != 5 ) {... }
Vincenzo Innocente - Corso breve OO x7b03a928 Puntatori Riferimento ad una locazione di memoria j 12 ptr int main() { int j = 12; return 0; } int *ptr = &j; #include cout << *ptr << endl; j = 24; cout << *ptr << endl; cout << ptr << endl; indirizzo di memoria 24
Vincenzo Innocente - Corso breve OO 19 Puntatori Puntatore nullo #include int main() { int j = 12; int *ptr = 0; cout << *ptr << endl; // crash ! return 0; } Segmentation violation (core dumped) j 12 ptr
Vincenzo Innocente - Corso breve OO 20 Puntatori: allocazione dinamica Riferimento ad una locazione di memoria #include int main() { int *ptr = new int; *ptr = 12; cout << *ptr << endl; delete ptr; return 0; } 12 ptr Attenzione: –Non usare delete fa accumulare locazioni di memoria inutilizzate (memory leak) –Utilizzare puntatori prima del new o dopo il delete causa il crash del programma
Vincenzo Innocente - Corso breve OO 21 Classi astratte Esempio classico: Shape Tutti oggetti nella finestra hanno comportamenti comuni che possono essere considerati in astratto:Tutti oggetti nella finestra hanno comportamenti comuni che possono essere considerati in astratto: –disegna, sposta, ingrandisci, etc.
Vincenzo Innocente - Corso breve OO 22 Circle.h Cerchio Costruttore Distruttore Nome della classe Punto e virgola! Point2d : classe che rappresenta un punto in 2 dimensioni. public: Circle(Point2d center, double radius); ~Circle(); void moveAt(const Point2d & p); void moveBy(const Point2d & p); void scale(double s); void rotate(double phi); void draw() const; void cancel() const; “Dati” privati (Attributi, membri) class Circle { }; private: Point2d center_; double radius_; Interfaccia Pubblica Metodi: operazioni sugli oggetti # include “Circle.h” void Circle::draw() const { const int numberOfPoints = 100; float x[numberOfPoints], y[numberOfPoints]; float phi = 0, deltaPhi = 2*M_PI/100; for ( int i = 0; i < numberOfPoints; ++i ) { x[i] = center_.x() + radius_ * cos( phi ); y[i] = center_.y() + radius_ * sin( phi ); phi += dphi; } polyline_draw(x, y, numberOfPoints ); } void Circle::moveAt( const Point2d& p ) { cancel(); center_ = p; draw(); } void Circle::scale( double s ) { cancel(); radius_ *= s; draw(); } Circle::Circle( Point2d c, double r ) : center_( c ), radius_( r ) { draw(); } Circle::~Circle() { cancel(); } Circle.cc #include “Circle.h” int main() { Circle c( Point2d(10, 10), 5 ); c.draw(); c.moveAt(Point2d(20, 30)); return 0; } Main.cc
Vincenzo Innocente - Corso breve OO 23 Quadrato class Square { public: Square(const Point2d&, const Point2d&); ~Square(); void moveAt( const Point2d& p ); void moveBy( const Point2d& p ); void scale( double s ); void rotate( double phi ); void draw() const; void cancel() const; private: Point2d center_; Vector2d centerToUpperCorner_; }; Square.h #include “Square.h” void Square::draw() const { float x[4], y[4]; Vector2d delta( centerToUpperCorner_ ); for ( int i = 0; i < 4; i++ ) { Point2d corner = center_ + delta; x[i] = corner.x(); y[i] = corner.y(); delta.rotate( M_PI_2 ); } polyline_draw(x, y, 4); } void Square::rotate( double phi ) { cancel(); centerToUpperCorner_.rotate( phi ); draw(); } Square::Square(const Point2d& lowerCorner, const Point2d& upperCorner ) : center_( median(lowerCorner, upperCorner) ), centerToUpperCorner_( upperCorner - center_ ) { draw(); } void Square::scale( double s ) { cancel(); centerToUpperCorner_ *= s; draw(); } Square.cc upperCorner loweCorner centerToUpperCorner _
Vincenzo Innocente - Corso breve OO 24 Codice Applicativo (Client) #include “Circle.h” #include “Square.h” int main() { Circle c1( Point2d(2.,3.), 4.23, ); Square r1( Point2d(2.,1.), Point2d(4.,3.) ); Circle * circles[ 10 ]; for ( int i = 0; i < 10; ++i ) { circles[ i ] = new Circle( Point2d(i,i), 2. ); } for ( int i = 0; i < 10; ++i ) circles[ i ]->draw(); return 0; } Main.cc Come gestire cerchi e quadrati insieme? Costruisce un vettore di puntatori a cerchi, crea oggetti in memoria e salva i loro puntatori nel vettore. Itera sul vettore e invoca draw() per ogni elemento
Vincenzo Innocente - Corso breve OO 25 Polimorfismo Tutte le Shapes hanno la stessa interfaccia: draw, pick, move, fillColor..., ma ogni sottotipo diverso può avere la usa personale implementazione
Vincenzo Innocente - Corso breve OO 26 class Shape { public: Shape() { } virtual ~Shape() { } virtual void moveAt( const Point2d& ) = 0; virtual void scale( double s ) = 0; virtual void rotate( double phi ) = 0; virtual void draw() const = 0; virtual void cancel() const = 0; }; Shape.h Interfaccia astratta Interfaccia di metodi puramente virtuali #include “Shape.h” class Square : public Shape { // …. Il resto tutto uguale a prima }; Square.h #include “Circle.h” #include “Square.h” int main() { Shape * shapes[ 10 ]; int index = 0; for ( int i = 0; i < 10; i++ ) { Shape * s; s = new Circle( Point2d(i, i), 2.) ); shapes[ index ++ ] = s; s = new Square( Point2d(i, i), Point2d(i+1, i+2)) ); shapes[ index ++ ] = s; } for ( int i = 0; i < 10; i++ ) shapes[ i ]->draw(); return 0; } Main.cc
Vincenzo Innocente - Corso breve OO 27 Ereditarietà e riuso del codice Class CenteredShape: public Shape { public: CenteredShape( Point2d c ) : center_( c ) { /*draw();*/ } ~Circle() { /*cancel();*/ } void moveAt( const Point2d& ); void moveBy( const Vector2d& ); virtual void scale( double ) = 0; virtual void rotate( double ) = 0; virtual void draw() const = 0; virtual void cancel() const = 0; protected: Point2d center_; }; CenteredShape.h Non si possono chiamare metodi virtuali in costruttori e distruttori (troppo presto, troppo tardi) #include “CenteredShape.hh” class Square : public CenteredShape { public: Square( Point2d lowerCorner, Point2d upperCorner ) : CenteredShape( median(lowerCorner, upperCorner) ), touc_(upperCorner - center_) { draw(); } ~Square() { cancel(); } virtual void scale( double s ) { cancel(); centerToUpperCorner_ *= s; draw(); } virtual void rotate( double phi ); virtual void draw() const; virtual void cancel() const; private: Vector2d touc_; }; Square.h
Vincenzo Innocente - Corso breve OO 28 Modello UML
Vincenzo Innocente - Corso breve OO 29 Programmazione generica Funzioni Generiche template inline T min(const T& a, const T& b) { return a < b ? a:b; } class P { public: P(int ix,int iy):x(ix),y(iy){} bool operator<(const P& b) const { return y<b.y ||( y==b.y && x<b.x ); } private: float x; float y; }; P.h int main() { float a = min(3.,2.); int i = min(2,3); P p1(1.,2.), p2(3.,1.); P p3 = min(p1,p2); return 0; } Main.cc Usa min Usa min “<” deve essere definito per “T”
Vincenzo Innocente - Corso breve OO 30 Programmazione generica Classi Generiche template class Vector3d { public: Vector3d(const T*a) { copy(a,a+3,&x[0]); } Vector3d & operator+=(const Vector3d & b) {x[0]+=b.x[0]; x[1]+=b.x[1]; x[2]+=b.x[2]; return *this;} private: T x[3]; }; Vector3d.h #include “vector3d.h” int main() { Vector3d a, b,c; c+=b+=a; Vector3d c1, c2; c2+=c1; return 0; } Main.cc Ritorna se stesso per permettere la concatenazione di operatori “copy” è una funzione generica di STL
Vincenzo Innocente - Corso breve OO 31 La libreria standard: std (STL) Contenitori generici: –vector, list, set, map, “ string ” Iteratori –puntatori “intelligenti” nei contenitori generici Funzioni generiche –copy, merge, find, sort, swap,… –agiscono su iteratori
Vincenzo Innocente - Corso breve OO 32 Un semplice vettore #include int main() { vector v; // creamo un vettore di interi vuoto cout << v.size() << endl; // stampa dimensione di v: zero for ( int i = 0; i != 10; ++i ) // un loop da 0 a 9 v.push_back( i ); // aggiungiamo un intero in coda a v cout << v.size() << endl; // stampa dimensione di v: 10 // creiamo un iteratore costante per un vettore di interi: // p si comporta come un “const int *” a tutti gli effetti vector ::const_iterator p; for ( p = v.begin(); p != v.end(); ++p ) // “itera dall’inizio alla fine di v” cout << (*p) << “ “; cout << endl; return 0; } Main.cc
Vincenzo Innocente - Corso breve OO 33 Un semplice vettore begin() end() end() p p pp p p
Vincenzo Innocente - Corso breve OO 34 Vettore di classe astratta Shape* #include “Circle.h” #include “Square.h” #include int main() { vector vs; // un vettore di puntatori a Shapes for ( int i = 0; i != 10; ++i ) { // aggiungiamo un puntatore ad un nuovo cerchio vs.push_back(new Circle(Point2d(i, i), 2.)); // aggiungiamo un puntatore ad un nuovo quadrato vs.push_back(new Square(Point2d(i, i), Point2d(i + 1, i + 2))); } // iteratore: essenzialmente un puntatore a Shape* ossia un Shape** vector ::const_iterator p; for ( p = vs.begin(); p != vs.end(); ++p ) // loop sull’intero vettore (*p)->draw(); // disegniamo ogni Shape return 0; } Main.cc
Vincenzo Innocente - Corso breve OO 35 Concetti Classici Riveduti Relazioni tra oggetti Decomposizione funzionale in una classe responsabilità dei metodi Decomposizione funzionale tra classi responsabilità delle classi
Vincenzo Innocente - Corso breve OO 36 Superfici e traiettorie Nel tracking spesso è necessario calcolare intersezioni tra curve (tracce) e superfici (elementi di detector)
Vincenzo Innocente - Corso breve OO 37 Superfici e traiettorie Interfaccia delle diverse Trajectory #include “Trajectory.h” class Line : public Trajectory { public: virtual Point position(double s); virtual Vector direction(double s); public: Point origin_; Vector direction_; }; Line.h #include “Trajectory.h” class Helix : public Trajectory { public: virtual Point position(double s); virtual Vector direction(double s); }; Helix.h class Trajectory { public: virtual Point position(double s) = 0; virtual Vector direction(double s) = 0; }; Trajectory.h
Vincenzo Innocente - Corso breve OO 38 Superfici e traiettorie Implementazione #include “Trajectory.h” // … vuoto... Trajectory.cc #include “Line.h” Line::Line(const Point& o, constVector& d) : origin_( o ), direction_( d.unit() ) { } Point Line::position(double s) { return ( origin_ + s * direction_ ); } Line.cc #include “Helix.h” Helix::Helix() { } Point Helix::position(double s) { // implementazione } Helix.cc
Vincenzo Innocente - Corso breve OO 39 #include “Surface.h” class Plane : public Surface { public: virtual distance(const Point& p); virtual derDist(const Point& p, const Vector& r); protected: Point origin_; Vector norm_; double dist_; }; Plane.h class Surface { public: virtual distance(const Point& p) = 0; virtual derDist(const Point& p, const Vector& r) = 0; }; Surface.h Superfici e traiettorie Interfaccia delle varie Surface #include “Surface.h” class Cylinder : public Surface { public: virtual distance(const Point& p); virtual derDist(const Point& p, const Vector& r); }; Cylinder.h distanza (con segno) di un punto dalla superficie
Vincenzo Innocente - Corso breve OO 40 Superfici e traiettorie Surface è una classe astratta #include “Plane.h” Plane::distance(const Point& p) { return ( _dist - ( (p - origin_) * direction_) ); } Plane::derDist(const Point& p, const Vector& r) { return - r * _direction; } Plane.cc #include “Cylinder.h” Cylinder::distance(const Point& p) { /*... */ } Cylinder::derDist(const Point& p, const Vector& r) { /*... */ } Cylinder.cc #include “Surface.h” // vuoto Surface.cc
Vincenzo Innocente - Corso breve OO 41 Superfici e traiettorie Interfaccia di Intersection class Surface; class Trajectory; class Intersection { public: Intersection(Surface* s, Trajectory* t) surface_(s), trajectory_(t) {} Point intersect(double s1, double s2); protected: double sIntersect(double s1, double s2); Surface* surface_; Trajectory* trajectory_; }; Intersection.h forward class declaration
Vincenzo Innocente - Corso breve OO 42 Superfici e traiettorie Implementazione dell’algoritmo #include “Intersection.h” #include #include “Surface.h” #include “Trajectory.h” const int maxIterations 20 const double sMax 1.e+6 const double accuracy1.e-3 double Intersection::sIntersect(double s1, double s2) { // algoritmo di Newton-Raphson double s = s1; double maxS = max(s1, s2); double minS = min(s1, s2); double d, delta; for( int j = 0; j < maxIterations; j++ ) { Point p = _trajectory->position( s ); d = surface_->distance( p ); delta = surface_->derDist( p, trajectory_->direction( s ) ); double ds = - d / delta; double test = s + ds; Intersection.cc // controlla che test è tra s1 e s2 if( (s1 - test) * (test - s2) < 0.0 ) { if ( s1 < s2 ) s += abs( d ); else s -= abs( d ); if( s > maxS || s < minS ) return sMax; } else s = test; if( abs(d) < accuracy ) return s; } return sMax; } Point Intersection::intersect(double s1, double s2) { return trajectory_->position(sIntersect(s1, s2)); }
Vincenzo Innocente - Corso breve OO 43 Superfici e traiettorie Intersection usa solo: –I metodi position e direction di un’oggetto Trajectory –I metodi distance e derDist di un oggetto Surface E’ possibile aggiungere una nuova classe che modellizza una nuova Trajectory o una nuova Surface e I ntersection continua a funzionare senza modificare una linea di codice! E’ possibile rendere anche Intersection astratto...
Vincenzo Innocente - Corso breve OO 44 “Open/Closed principle” Un buon codice deve essere –aperto ad estensioni –chiuso a modifiche Modificare un codice funzionante può introdurre bachi… L’Object Oriented, con il meccanismo delle classi virtuali, permette di applicare questo principio
Vincenzo Innocente - Corso breve OO 45 Disegno a oggetti:Modello di Hardware DAQ Costruiamo un modello del Hardware per un sistema di acquisizione –“Use Cases”: gestione delle parti (dove sono, a chi appartengono) simulazione (potenza dissipata, spazio occupato) controllo on-line (on/off, temperatura, voltaggio) DAQ (questi dati da dove vengono?) calibrazione (piedistalli, guadagni, fattori di conversione)
Vincenzo Innocente - Corso breve OO 46 Chi sono i giocatori? I componenti Hardware: Racks, crates, moduli di vario tipo e foggia “Utenti” (persone, displays, interfacce) conviene avere un “corrispondente” nel modello Primi candidati a classi e oggetti
Vincenzo Innocente - Corso breve OO 47 Un primo modello
Vincenzo Innocente - Corso breve OO 48 Calcolo della potenza in un rack
Vincenzo Innocente - Corso breve OO 49 La base di un modello composto
Vincenzo Innocente - Corso breve OO 50 #include “DaqComponent.h” class DaqLeaf: public DaqComponent { public: explicit DaqLeaf( float ip = 0 ): power_(ip) {} virtual float power() const { return power_;} } protected: float power_; }; DaqLeaf.h Codice del modello composto class DaqComposite; // forward declaration class DaqComponent { public: DaqComponent() : parent_(0) {} virtual float power() const = 0; protected: DaqComposite * parent_; }; DaqComponent.h
Vincenzo Innocente - Corso breve OO 51 Codice del modello composto #include “DaqComponent.h” class DaqComposite : public DaqComponent { public: DaqComposite(){} virtual float power() const { float totalPower = 0; vector ::const_iterator p; for( p = components.begin(); p != components.end(); ++p ) { totalPower += (*p)->power(); } return totalPower; } protected: vector components; }; DaqComposite.h
Vincenzo Innocente - Corso breve OO 52 Le classi “concrete”
Vincenzo Innocente - Corso breve OO 53 Aggiungiamo un inventario
Vincenzo Innocente - Corso breve OO 54 Dove si trova un componente? Dato un componente vogliamo sapere la sua locazione globale –La risposta è una stringa che concatena le locazioni locali (room, rack, crate, module) –Chi è responsabile della conoscenza della locazione: il componente o il composito? Entrambe le soluzioni hanno pro e contro Una soluzione “flessibile” è assegnare la locazione all’associazione di composizione
Vincenzo Innocente - Corso breve OO 55 Locazione di un componente In C++: DaqComponent punterà a Location DaqComposite avrà un vettore di (puntatori a) Location s Location (oltre ad un identificatore) punterà a DaqComponent e DaqComposite Location può essere una classe astratta e la rappresentazione del suo identificare può così dipendere dal tipo di composito (un intero per la slot di un modulo in un crate, una stringa per la posizione di un rack in una stanza)
Vincenzo Innocente - Corso breve OO 56 Stampa della locazione globale Per ottenere una stringa che identifichi la posizione globale, ogni componente prima invoca la locazione del suo genitore e poi stampa la propria locazione (delegando quest’ultima operazione a Location per essere indipendente dalla rappresentazione concreta dell’identificatore della locazione stessa)
Vincenzo Innocente - Corso breve OO 57 Conclusioni La programmazione C++ Object Oriented può aiutare a ridurre le dipendenze all’interno del codice e quindi lo sviluppo del programma... … ma va utilizzato in maniera adeguata, disegnando il codice prima di implementarlo è facile scrivere un codice C++ traslitterando un codice F77, ma questo non produce grandi miglioramenti
Vincenzo Innocente - Corso breve OO 58 Fine