La presentazione è in caricamento. Aspetta per favore

La presentazione è in caricamento. Aspetta per favore

Introduzione al C++ e alla programmazione ad oggetti Introduzione al C++ e alla programmazione ad oggetti Corso Specialistico CNTC Bologna, 19-23 febbraio.

Presentazioni simili


Presentazione sul tema: "Introduzione al C++ e alla programmazione ad oggetti Introduzione al C++ e alla programmazione ad oggetti Corso Specialistico CNTC Bologna, 19-23 febbraio."— Transcript della presentazione:

1 Introduzione al C++ e alla programmazione ad oggetti Introduzione al C++ e alla programmazione ad oggetti Corso Specialistico CNTC Bologna, febbraio 2001 Andrea DellAcqua e Claudio Grandi

2 Introduzione al C++ e alla programmazione ad oggetti febbraio Introduzione Le due componenti principali dei programmi: –Algoritmi: linsieme delle istruzioni che svolgono un particolare compito –Dati: ciò su cui gli algoritmi agiscono per produrre una soluzione unica La relazione fra queste componenti definisce il paradigma di programmazione –Programmazione procedurale: problemi modellati dagli algoritmi. Dati immagazzinati in aree comuni o passate agli algoritmi –Programmazione ad oggetti: problemi modellati dalle relazioni fra tipi di dati astratti (ADT, Abstract Data Types), chiamati generalmente oggetti

3 Introduzione al C++ e alla programmazione ad oggetti febbraio Il rapporto Dato-Algoritmo Linguaggio Bits Bits macchina Programmazione Dati Algoritmi Livello di astrazione Assemblers Symbolic Op-code Words Compilatori Variables & Statements Types Linguaggi Data Subroutines strutturati structures Ada (Modula) Abstract Packages Data Types (Modules) Object Oriented Objects Objects

4 Introduzione al C++ e alla programmazione ad oggetti febbraio Cosè un oggetto? Né più né meno di quello che potreste trovare scritto in un vocabolario… –Un oggetto è unentità che si possa immaginare dotata di determinate caratteristiche e funzionalità. Lo stato di un oggetto è rappresentato da dati che ne descrivono le caratteristiche in un certo istante Le funzionalità di un oggetto sono le operazioni che può svolgere quando glie lo si richiede (cioè quando riceve un messaggio) Nella nostra vita quotidiana siamo molto più abituati a ragionare per oggetti che non in modo strutturato!

5 Introduzione al C++ e alla programmazione ad oggetti febbraio Un esempio...

6 Introduzione al C++ e alla programmazione ad oggetti febbraio SoldatoSoldato

7 Introduzione al C++ e alla programmazione ad oggetti febbraio Funzione Codice funzione Codice funzione Codice funzione … cosè un oggetto: Un insieme di dati e funzioni: Dato

8 Introduzione al C++ e alla programmazione ad oggetti febbraio Incapsulazione Netta divisione fra interfaccia e implementazione Da fuori si vede solo linterfaccia che definisce i messaggi accettati dalloggetto I dettagli dellimplementazione (dati e codice delle funzioni) sono invisibili dallesterno Ogni oggetto ha in se tutto ciò che gli serve per rispondere alle chiamate (o deve sapere a chi chiedere…) Il confinamento di informazioni e funzionalità in oggetti permette livelli maggiori di astrazione e semplifica la gestione di sistemi complessi.

9 Introduzione al C++ e alla programmazione ad oggetti febbraio Approccio OO Sono le strutture di dati che svolgono le azioni, non le subroutines Il lavoro è svolto dal server, non dal client Cos è? Com è fatto? Data Oriented Cosa può fare per me? Object Oriented

10 Introduzione al C++ e alla programmazione ad oggetti febbraio Perché programmare per oggetti? Programmare per oggetti non velocizza lesecuzione dei programmi... Programmare per oggetti non ottimizza luso della memoria... E allora perchè programmare per oggetti? Programmare per oggetti facilita la progettazione e il mantenimento di sistemi software molto complessi!

11 Introduzione al C++ e alla programmazione ad oggetti febbraio Caratteristiche del software non mantenibile Rigidità –non può essere cambiato con faciltà –non può essere stimato limpatto di una modifica Fragilità –una modifica singola causa una cascata di modifiche successive –i bachi sorgono in aree concettualmente separate dalle aree dove sono avvenute le modifiche Non riusabilità –esistono molte interdipendenze, quindi non è possibile estrarre parti che potrebbero essere comuni

12 Introduzione al C++ e alla programmazione ad oggetti febbraio Programmazione ad oggetti La programmazione ad oggetti, attraverso lincapsulazione, consente di: –ridurre la dipendenza del codice di alto livello dalla rappresentazione dei dati –riutilizzare del codice di alto livello –sviluppare moduli indipendenti luno dallaltro –avere codice utente che dipende dalle interfacce ma non dallimplementazione

13 Introduzione al C++ e alla programmazione ad oggetti febbraio C++ e Object Orientation Il C++ può essere usato come linguaggio procedurale o per programmazione ad oggetti Object Orientation implementata attraverso il concetto di classe Prima di affrontare il problema della programmazione OO con C++ dobbiamo: –capire dove la programmazione procedurale fallisce –affrontare la sintassi del C++

14 Introduzione al C++ e alla programmazione ad oggetti febbraio Programmazione procedurale 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))/... 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 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) 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?

15 Introduzione al C++ e alla programmazione ad oggetti febbraio 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)) 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 FUNCTION COSTHETA1(THETA1, THETA2, + PHI1, PHI2) COSTHETA1 = SIN(THETA1)*SIN(THETA2) * + COS(PHI1-PHI2) + COS(THETA1)*COS(THETA2) END...e il codice!

16 Introduzione al C++ e alla programmazione ad oggetti febbraio COMMON /MYDATA/ P1(4), P2(4), + P3(4), P4(4) COSTHETA12 = COSTHETA(P1, P2) COSTHETA13 = COSTHETA(P1, P3) COSTHETA14 = COSTHETA(P1, P4) 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 Nellesempio 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 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

17 Introduzione al C++ e alla programmazione ad oggetti febbraio OO riduce le dipendenze! 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 Supporta tipi di dati astratti (vedere seguito... )

18 Introduzione al C++ e alla programmazione ad oggetti febbraio Sintassi: FORTRAN vs C / C++ Struttura del programma PROGRAM TEST C esempio di programma... END PROGRAM TEST C esempio di programma... END int main() { // esempio di programma... return 0; // fine } 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 ;

19 Introduzione al C++ e alla programmazione ad oggetti febbraio Il main program Ogni programma in C++, per essere eseguibile, deve contenere una funzione main() da cui lesecuzione comincerà main() deve avere un tipo (decidere quale è compito del programmatore). Regola generale è che main() ritorni un intero, a significare il return code dellapplicazione int main() { // il piu` semplice programma in C++ return 0; } int main() { // il piu` semplice programma in C++ return 0; }

20 Introduzione al C++ e alla programmazione ad oggetti febbraio I/O: lettura e scrittura Non esiste nel C++ nativo. Si usa: iostream –Gli operatori > sono usati per definire la direzione del flusso – cin, cout e cerr rappresentano lo standard input, output e error del programma #include int main() { return 0; } direttiva al preprocessore end of line #include cout << Hello, world ! << endl;

21 Introduzione al C++ e alla programmazione ad oggetti febbraio Commenti Esistono due tipi di commento in C++ –inline: –multiline (come in C ): –I due tipi possono essere usati indifferentemente, ma si raccomanda di usare linline (più semplice e meno ambiguo) const int Ntries; // questo e` un commento inline // il resto della linea e trattato come un commento const int Ntries; /* questo e` un commento multiline: tutto viene trattato come un commento fino a quando il commento stesso non viene chiuso con uno */

22 Introduzione al C++ e alla programmazione ad oggetti febbraio Tipi predefiniti in C++ Sono definiti una serie di tipi numerici che permettono di rappresentare numeri interi, reali e caratteri – char (un solo byte) viene normalmente usato per rappresentare interi inferiori a 256 –stringhe e numeri complessi sono implementati come tipi derivati intintero in singola precisione longintero in doppia precisione floatreale in singola precisione doublereale in doppia precisione long double reale in precisione estesa unsigned intintero senza segno unsigned doublereale senza segno in doppia precisione charcarattere singolo boolvariabili logiche

23 Introduzione al C++ e alla programmazione ad oggetti febbraio Tipi predefiniti in C++ (2) x123 interi costanti, decimale, ottale, esadecimale 123l 123uinteri, long, unsigned A 1 \t caratteri, tab 3.14f Lfloat, double, long double 300e-2.03e230e-1double, notazione esponenziale Nomestringa costante truefalseboolean Esempi di costanti \aalert \\backslash \bbackspace \rcarriage return \double quote \fform feed \ttab \nnewline \0carattere nullo \single quote \vvertical tab \ ottale, A \x041esadecimale, A Costanti carattere stringa nulla (\0) nomen o m e \0 una \stringa\stampa: una stringa una stringa \un \ alla fine della linea su piu` lineeper continuare la stringa Stringhe costanti

24 Introduzione al C++ e alla programmazione ad oggetti febbraio Tipi predefiniti in C++ (3) char [1] int [1] bool short [1] long [1] float double long double OS 16 bit OS 32 bit OS 64 bit [1] Può essere unsigned

25 Introduzione al C++ e alla programmazione ad oggetti febbraio Identificatori Un identificatore è composto da uno o più caratteri Il primo carattere deve essere una lettera o un underscore. Caratteri successivi possono essere lettere, numeri o underscore Non c è un limite in lunghezza, anche se alcuni sistemi si limitano a considerare i primi 31 caratteri Gli identificatori che iniziano con un doppio underscore o con un underscore e una lettera maiuscola sono riservati ad usi di sistema C++ e` case sensitive! const int Ntries; double _attempts; double 2A; // errore!

26 Introduzione al C++ e alla programmazione ad oggetti febbraio Keywords Alcuni identificatori sono esplicitamente riservati al sistema (hanno un preciso significato in C++ ) e non possono essere usati asmelseoperatorthrow autoenumprivatetrue boolexplicitprotectedtry breakexternpublictypedef casefalseregistertypeid catchfloatreinterpret_casttypename charforreturnunion classfriendshortunsigned constgotosignedusing const_castifsizeofvirtual continueinlinestaticvoid defaultintstatic_castvolatile deletelongstructwchar_t do mutableswitchwhile doublenamespacetemplate dynamic_castnewthis keyword

27 Introduzione al C++ e alla programmazione ad oggetti febbraio const La keyword const viene utilizzata per dichiarare un oggetto costante In C le costanti vengono normalmente dichiarate usando il preprocessore –in questo caso N e` una costante senza tipo ed il preprocessore sostituisce N ovunque lo trovi nel programma, senza rispettare le regole di scope (da evitare) const int N=100;N non puo` essere cambiato double w[N];N usato come per dimensionare un vettore const int vect[5]=le componenti di vect non {10,20,30,40,50};possono essere cambiate Esempi di const #define N 100

28 Introduzione al C++ e alla programmazione ad oggetti febbraio Dichiarazione Le dichiarazioni associano un significato ad un identificatore in C++ ogni cosa deve essere dichiarata per poter essere usata Una dichiarazione è spesso anche una definizione. Per variabili semplici questo consiste nellassociare un valore alla variabile al momento della dichiarazione const int i;// la variabile i double max(double r1,double r2);// la funzione max const double pi= ;// definizione double max(double r1, double r2) {// dichiarazione return (r1>r2) ? r1: r2; // definizione di max }

29 Introduzione al C++ e alla programmazione ad oggetti febbraio typedef Listruzione typedef viene utilizzata per creare un alias per tipi esistenti typedef NON può essere usato per implementare nuovi tipi, ma solo per definire un alias typedef int INTEGER;// per i nostalgici del fortran typedef int BOOLEAN;// usato prima che bool venisse // implementato typedef void (*ptr_f)(); // ptr_f e` un puntatore ad una // procedura (subroutine) typedef mela frutto;// compila soltanto se mela // e` gia` stata definita

30 Introduzione al C++ e alla programmazione ad oggetti febbraio Enumeratori In C++ sono supportati tipi definiti dallutente enum Color { red, green, blue }; Color screenColor = blue; Color windorColor = red; int n = blue; // valido Color c = 1; // errore enum Seme { cuori, picche, quadri, fiori };

31 Introduzione al C++ e alla programmazione ad oggetti febbraio Scope Le variabili possono essere dichiarate e definite quasi ovunque in un programma in C++ la visibilità (scope) di una variabile dipende da dove la variabile è stata dichiarata int func() { … const int n=50;// function scope for (int i=0;i<100;i++)// i e` locale { double r;// r e` locale... } cout<

32 Introduzione al C++ e alla programmazione ad oggetti febbraio Scope (2) Attenzione! La stessa variabile può essere ri- dichiarata (con visibilità diversa). Questo è da evitare (se possibile) per non rendere il programma oscuro e a rischio di errore! int i;// file (global) scope int func() { int i=50;// function scope, nasconde // la i a file scope for (int i=0;i<100;i++)// block scope. Nasconde // la i a function scope { int i;// questo e` un errore } cout<

33 Introduzione al C++ e alla programmazione ad oggetti febbraio namespace Funzioni e variabili definite a global scope sono visibili dappertutto in un programma in C++ –Per evitare che funzioni diverse (definite in librerie diverse) con lo stesso nome possano interferire (name clash), C++ implementa il concetto di namespace, che introduce un ulteriore, più alto livello di scope namespace mynames { int i;// la mia dichiarazione di i float max(float, float);// la mia dichiarazione di max } float mynames::max(float a, float b)// implementazione della {// funzione max appartenente return (a>b) ? a : b;// al namespace mynames }

34 Introduzione al C++ e alla programmazione ad oggetti febbraio namespace (2) Per utilizzare variabili e funzioni racchiuse in un namespace si può: –o accedere allintero namespace –oppure accedere alla singola variabile o funzione –oppure dichiarare la singola funzione using namespace mynames;... float r = max (2.1f, 5.3f); float r = mynames::max (2.1f, 5.3f); using mynames::max;... float r = max (2.1f, 5.3f);

35 Introduzione al C++ e alla programmazione ad oggetti febbraio i+wpiu` e meno unari a*ba/bi%2moltiplicazione, divisione, modulo a+ba-baddizione e sottrazione binarie a=3;assegnazione Espressioni AritmeticheCommento Operatori k = ++j; j=j+1; k=j; k = j++; k=j; j=j+1; k = --j; j=j-1; k=j; k = j--; k=j; j=j-1; Auto-incremento Espressione e decremento ~i; Complemento bit a bit i&j; AND bit a bit i|j OR bit a bit i^j XOR bit a bit i<>n shift a destra di n pos. bit-wise significato maggiore di.GT. <=minore o uguale.LE. >=maggiore o uguale.GE. ==uguale.EQ. !=diverso.NE. !Negazione unaria.NOT. &&and logico.AND. ||or logico.OR. Operatori relazionaliFortran

36 Introduzione al C++ e alla programmazione ad oggetti febbraio Espressioni di assegnazione Le espressioni di assegnazione sono valutate da destra a sinistra Le assegnazioni multiple sono permesse alcuni operatori di assegnazione combinano assegnazione ed altri operatori Assegnazioni possono essere fatte allinterno di espressioni aritmetiche a = j++; j viene incrementato ed il risultato assegnato ad a a = b = c = d = 100; a *= b;// equivale ad a = a*b; a -= b;// equivale ad a = a-b; a = b + ( c = 3 );// equivale a c=3; a=b+c;

37 Introduzione al C++ e alla programmazione ad oggetti febbraio Statements vuoto; espressionej=j+k; composto{.... }usato in funzioni, if.. Costituisce un blocco goto goto label;da non usarsi ifif (p==0) cerr<0); breakbreak;esce dal blocco continuecontinue;prossima iterazione StatementC++commenti

38 Introduzione al C++ e alla programmazione ad oggetti febbraio Statements (2) switchswitch (s) { case 1:si deve usare break per ++i;evitare di cadere nei case 2:casi successivi e --i;aggiungere un caso di default:default alla fine della ++j;lista }; dichiarazioneint i=7;in un blocco, file o namespace trytry {....}usato per trattare le eccezioni labelerror: cerr<

39 Introduzione al C++ e alla programmazione ad oggetti febbraio Statement composti Uno statement composto in è costituito da una serie di statement contenuti fra parentesi graffe Usato normalmente per raggruppare istruzioni in un blocco ( if, for, while, do-while, etc.) Il corpo di una funzione è sempre uno statement composto La dichiarazione di una variabile può avvenire ovunque allinterno di un blocco, in questo caso lo scope della variabile sarà il blocco stesso Ovunque si possa usare uno statement singolo si può definire un blocco

40 Introduzione al C++ e alla programmazione ad oggetti febbraio if Attenzione alluso di = e == Nel dubbio, usare sempre un blocco… Attenzione agli else! if (i=1)// questo e` sempre vero!!! {....} if (i != 0)// possibile divisione per 0 a++;// mancano delle {}? a/=i; if (i == 0)// possibile divisione per 0 if (a<0) { cerr<

41 Introduzione al C++ e alla programmazione ad oggetti febbraio while e do-while La forma generale di un while è : Lo statement verrà eseguito fino a quando la condizione verrà verificata ( true ). A seconda del volore della condizione, lo statement verrà eseguito zero o più volte la sintassi di un do-while è invece: Lo statement verrà quindi eseguito almeno una volta while (condizione) statement; do statement; while (condizione);

42 Introduzione al C++ e alla programmazione ad oggetti febbraio break e continue break e continue sono utilizzati nei loop per saltare alla fine del loop o fuori dal loop stesso break e continue possono solamente essere utilizzati nel corpo di un for, while o do- while. break e` anche usato negli switch int i,n=0; int a[100]; cin>>i;// leggo il valore di i while (1)// loop infinito { if (i<0) break; if (n>=100) continue; a[n]=i; n++; // continue salta qui } // break salta qui

43 Introduzione al C++ e alla programmazione ad oggetti febbraio switch Lo switch è uno statement condizionale che generalizza lo if-else lo statement è generalmente composito e consiste di diversi case e, opzionalmente, di un default switch (condizione) (statement); switch (n) { case 0: cout<< n e` nullo<

44 Introduzione al C++ e alla programmazione ad oggetti febbraio switch (2) Non si puo` dichiarare una variabile in uno dei case … ma si puo` creare una variabile locale definendo uno statement composto... switch (k) { case 0: int j=0;// Illegale! Errore!... case 1:... } switch (k) { case 0: { int j=0;// OK, questo compila... } case 1:... }

45 Introduzione al C++ e alla programmazione ad oggetti febbraio Loperatore ? Loperatore ? e` lunico esempio di operatore ternario in C++ –Equivale a: –Esempio: expr1 ? expr2 : expr3; double max(double a, double b) { double max = (a>b) ? a : b; return max; } if(expr1) expr2; else expr3;

46 Introduzione al C++ e alla programmazione ad oggetti febbraio Sintassi: FORTRAN 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 ) {... } for (i = 1; i <= 10; i++) {... } if (i == 10 && j > 4 || x) {... } while( x != 5 ) {... }

47 Introduzione al C++ e alla programmazione ad oggetti febbraio int main() { return 0; } int main() { return 0; } Funzioni matematiche In C++ non esistono funzioni predefinite cmath.h definisce sin, cos,... { double r, theta, phi; #include cin >> r >> theta >> phi ; #include double x = r * sin( theta ) * sin( phi ); double y = r * sin( theta ) * cos( phi ); double z = r * cos( theta ); cout << x <<, << y <<, << z << endl; Potenze: pow(b,exp) (non si può usare ** )

48 Introduzione al C++ e alla programmazione ad oggetti febbraio Array Sono supportati gli array di dimensione fissa int main() { int x[10]; for ( int i = 0; i < 10, i++ ) x[i] = 0; double m[5][5]; for ( int i = 0; i < 5; i++ ) for ( int j = 0; j < 5; j++ ) m[i][j] = i * j; return 0; } int main() { int x[10]; for ( int i = 0; i < 10, i++ ) x[i] = 0; double m[5][5]; for ( int i = 0; i < 5; i++ ) for ( int j = 0; j < 5; j++ ) m[i][j] = i * j; return 0; } Lindice va da 0 a n-1. Usare un indice maggiore di n-1 può causare un crash. int x[] = { 1, 2, 3, 4 }; char[] t = { C, i, a, o, \0 }; char[] s = Ciao; int m[2][3] = { {11, 12, 13}, {21, 22, 23} }; Inizializzazione:

49 Introduzione al C++ e alla programmazione ad oggetti febbraio Esempio con gli arrays Moltiplicazione fra matrici: int main() { const int DIM=3; float m[DIM][DIM], m1[DIM][DIM], m2[DIM][DIM]; // Assumiamo che m1 ed m2 vengano riempiti qui... // Moltiplicazione: for (int i=0; i

50 Introduzione al C++ e alla programmazione ad oggetti febbraio x7b03a928 Puntatori Riferimento ad una locazione di memoria j 12 ptr int main() { int j = 12; return 0; } 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

51 Introduzione al C++ e alla programmazione ad oggetti febbraio Puntatori Puntatore nullo #include int main() { int j = 12; int *ptr = 0; cout << *ptr << endl; // crash ! return 0; } #include int main() { int j = 12; int *ptr = 0; cout << *ptr << endl; // crash ! return 0; } Segmentation violation (core dumped) j 12 ptr

52 Introduzione al C++ e alla programmazione ad oggetti febbraio Puntatori e array In C gli array sono trattati come puntatori int main() { float x[5]; int j; for (j = 0; j < 5; j++) x[j] = 0; float *ptr = x; *ptr = 1.5; // x[0] = 1.5 *(ptr+1) = 2.5; // x[1] = 2.5 *(ptr+3) = 3.5; // x[3] = 3.5 } x X[0] 1.5 X[1]X[2]X[3]X[4] X+1X+3

53 Introduzione al C++ e alla programmazione ad oggetti febbraio 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; } #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

54 Introduzione al C++ e alla programmazione ad oggetti febbraio Puntatori: allocazione dinamica Riferimento a più locazioni di memoria #include int main() { int *ptr = new int[3]; ptr[0] = 10; ptr[1] = 11; ptr[2] = 12 delete [] ptr; return 0; } #include int main() { int *ptr = new int[3]; ptr[0] = 10; ptr[1] = 11; ptr[2] = 12 delete [] ptr; return 0; } 10 ptr 1112

55 Introduzione al C++ e alla programmazione ad oggetti febbraio new e delete Gli operatori new and delete vengono utilizzati per allocazione/deallocazione di memoria dinamica – la memoria dinamica (heap), è unarea di memoria libera provvista dal sistema per quegli oggetti la cui durata di vita è sotto il controllo del programmatore new riserva la quantità necessaria di memoria richiesta e ritorna lindirizzo di questarea int *i=new int;alloca un intero, returna il puntatore char *c=new char[100];alloca un array (stringa) di 100 caratteri int *i=new int(99);alloca un intero e lo inizializza a 99 char *c=new char(c);alloca un carattere inizializzato a c int *j=new int[n][4];alloca un array di puntatori ad intero operatore newcommenti

56 Introduzione al C++ e alla programmazione ad oggetti febbraio new e delete (2) Loperatore delete è usato per restituire una certa area di memoria (allocata con new ) allo heap Ogni oggetto allocato con new deve essere distrutto con delete se non viene piu` utilizzato, altrimenti larea di memoria che esso occupata non potra` piu` essere ri-allocata (memory leak) Largomento di delete è tipicamente un puntatore inizializzato preventivamente con new delete ptr;distrugge un puntatore ad un oggetto delete p[i];distrugge loggetto p[i] delete [] p; distrugge ogni oggetto di tipo p operatore deletecommenti

57 Introduzione al C++ e alla programmazione ad oggetti febbraio new e delete (3) Attenzione –la dimensione dello heap non e` infinita –lallocazione con new può fallire, nel qual caso new restituisce un puntatore nullo o suscita uneccezione. Nel caso di allocazione di memoria importante bisogna verificare che loperazione abbia avuto successo prima di usare il puntatore –ogni oggetto creato con new deve essere distrutto con delete, ogni oggetto creato con new [] deve essere distrutto con delete [], queste forme NON sono intercambiabili

58 Introduzione al C++ e alla programmazione ad oggetti febbraio Regole di conversione e cast In C++ esistono conversioni esplicite ed implicite. –Le conversioni implicite (e.g. int float ) nelle espressioni aritmetiche, nel passare i parametri ad una funzione o nel ritornare un valore da una funzione rendono il meccanismo di conversione molto conveniente ma anche potenzialmente pericoloso (errori a run time) char, short e bool vengono promossi ad int Tipi interi che non possono essere rappresentati con un int vengono promossi a unsigned In una espressione di tipo misto, gli operandi di ordine inferiore vengono promossi allordine superiore secondo la gerarchia: int

59 Introduzione al C++ e alla programmazione ad oggetti febbraio Regole di conversione e cast (2) Ogni genere di puntatore può essere convertito in un puntatore generico a void Al contrario di quanto avviene in C, un puntatore generico non è compatibile con un puntatore di tipo arbitrario ma richiede un cast esplicito Ogni puntatore puo` essere inizializzato a 0 senza bisogno di un cast esplicito. In C++ usare 0 e non NULL per i puntatori! char *ch; void *generic_p;... generic_p=ch;// OK, char* va in void* ch=generic_p;// OK in C, illegale in C++ ch=(char *)generic_p; // OK, C e C++ arcaico

60 Introduzione al C++ e alla programmazione ad oggetti febbraio Casting in ANSI C++ Data la complessità delle operazioni di casting in C++ nuovi operatori di casting sono stati aggiunti a quelli già esistenti in C Esiste anche un dynamic_cast, utilizzato per riconoscere il tipo di un oggetto a run-time (RTTI) x=(float) i;cast in C++ - notazione C x=float(i);cast in C++, notazione funzionale x=static_cast (i);ANSI C++ - raccomandato i=reinterpret_cast (&x)ANSI C++, non portabile e system dependent func(const_cast (c_var))dove C_var e` una variabile dichiarata const. Usato per eliminare la const-ness per chiamare func Castcommenti

61 Introduzione al C++ e alla programmazione ad oggetti febbraio Funzioni In C++ le funzioni sono caratterizzate da un nome, dal tipo della variabile ritornata e da una lista di parametri (opzionali) La lista dei parametri (anche se vuota) deve essere esplicitata Il valore ritornato deve essere compatibile, a meno di conversione esplicita, con il tipo della funzione Valore di ritorno double max( double a, double b) { return (a>b) ? a : b; } Tipo ritornatoParametri Corpo della funzione

62 Introduzione al C++ e alla programmazione ad oggetti febbraio Funzioni (2) funzione double cube(double x) parametri passati { return x*x*x; } by value procedura void pr_square(int i) subroutine, non si { cout<

63 Introduzione al C++ e alla programmazione ad oggetti febbraio Prototipi delle funzioni Prima di essere usata, una funzione deve essere dichiarata (nel file che la usa) I prototipi rendono le funzioni in C++ type safe, nel senso che i valori reali degli argomenti vengono alloccorrenza convertiti nei tipi formali specificati dal prototipo #include double max(double, double); int main() { double m = max(1, 3); cout<b) ? a : b; } double max (double a, double b) { return (a>b) ? a : b; } max.cc Prototipo di max (normalmente in max.h )

64 Introduzione al C++ e alla programmazione ad oggetti febbraio Call-by-Reference Luso dei riferimenti permette ad una funzione di modificare il valore dei suoi argomenti –Per ragioni di efficenza, oggetti di grandi dimensioni (in termini di memoria) vengono normalmente passati by reference. –Per evitare che possano essere modificati dalla funzione, il riferimento viene definito const bool greater(int& i, int& j) { // se i>j scambia i e j if (i>j) { int temp=i; i=j; j=temp; return true; } else return false; } Argomenti passati by reference possono essere modificati dalla funzione stessa

65 Introduzione al C++ e alla programmazione ad oggetti febbraio Funzioni inline La keyword inline suggerisce al compilatore che ogni chiamata alla funzione deve essere convertita in codice eseguibile (la definizione della funzione viene sostituita alla chiamata dovunque nell codice) Le funzioni inline vengono usate per ragioni di efficienza e (per non sovraccaricare il compilatore) devono essere semplici Il compilatore può decidere autonomamente (per esempio se la funzione è troppo lunga) di ignorare la direttiva inline

66 Introduzione al C++ e alla programmazione ad oggetti febbraio Argomenti di default Ad ogni parametro di una funzione può essere assegnato un valore di default. Questo permette di chiamare la funzione tralasciando quei parametri il cui valore di default risulta appropriato Solo ai parametri più a destra nella calling sequence può essere dato un default. int pow(int, int); int main() { int r=3; int a1=pow(3,3); // a1=27 int a2=pow(3); // a2=9 return 0; } int pow(int, int); int main() { int r=3; int a1=pow(3,3); // a1=27 int a2=pow(3); // a2=9 return 0; } main.cc int pow (int a, int k=2) { if (k==2) return a*a; else return a*pow(a, k-1); } int pow (int a, int k=2) { if (k==2) return a*a; else return a*pow(a, k-1); } pow.cc Argomento di default

67 Introduzione al C++ e alla programmazione ad oggetti febbraio Overloading Funzioni diverse possono avere lo stesso nome La funzione che viene chiamata è scelta dal compilatore in base al tipo di ritorno ed al numero e tipo degli argomenti double average_array(const int a[], int size) { int sum=0; for (int i=0;i

68 Introduzione al C++ e alla programmazione ad oggetti febbraio Overloading (2) La lista dei tipi degli argomenti di una funzione è chiamata signature Il tipo ritornato dalla funzione non fa parte della signature, mentre il numero e lordine degli argomenti è cruciale void print(int i=0) {...}// (1) void print(int i, double x) {...}// (2) void print(double y, int i) {...}// (3)... print(A); // A e` convertito a int, chiama (1) print(str[]); // errore! Non e` possibile una conversione print(15,9);// errore! Ambiguita` fra (2) e (3) print(15,9.);// OK, chiama (2) print();// OK, chiama (1) con il default

69 Introduzione al C++ e alla programmazione ad oggetti febbraio Lalgoritmo di selezione Lutente può sempre utilizzare una conversione forzata (type cast) per ottenere una corrispondenza Il compilatore segnala tutti i casi in cui esiste ambiguità Ricerca della corrispondenza esatta Promozioni standard degli argomenti Conversioni standard dei tipi Conversioni definite dallutente Corrispondenza con lellipsi (…) int long int float traccia int I tentativi del compilatore

70 Introduzione al C++ e alla programmazione ad oggetti febbraio Funzioni esterne Si possono chiamare funzioni FORTRAN da C++: SUBROUTINE HBOOK1(ID, TITLE, NBIN, MIN, MAX, OPT) SUBROUTINE HFILL(ID,X, Y, WEIGHT) extern C void hbook1_(int&, char*, int&, float&, float&, float&, int); extern C void hfill_(int&, float&, float&, float&);... hbook1_(100, title, ……) // BUS ERROR!!! (il FORTRAN passa // sempre by-reference int id=100; hbook1_(id, title, ……) // OK!

71 Introduzione al C++ e alla programmazione ad oggetti febbraio Parametri del programma Dotando main() di una lista di argomenti, è possibile avere accesso ai parametri passati dalla command line: argc è il numero di parametri passati dalla command line (sempre almeno 1, il nome del programma) mentre il vettore di stringhe argv contiene ogni singolo parametro #include int main(int argc, char *argv[]) { cout<< argc e`: <

72 Introduzione al C++ e alla programmazione ad oggetti febbraio Parametri del programma (2) Lanciato con il comando prompt> mytest questo e un test il programma produrra` il seguente output: argc e` : 5 il nome delleseguibile e`/user/andrea/myprogram Argomento #1 = questo Argomento #2 = e Argomento #3 = un Argomento #4 = test

73 Introduzione al C++ e alla programmazione ad oggetti febbraio Organizzazione dei files Normalmente, le dichiarazioni delle interfacce e le specifiche sono separate dallimplementazione –header files (.h o.hh ) inclusi nei file sorgente utilizzando direttive del precompilatore non contengono codice eseguibile (con leccezione delle definizioni delle funzioni inline) non devono essere inclusi piu` di una volta, per evitare problemi con il linker #include #ifndef MyHeader_H #define MyHeader_H // dichiarazioni ….. #endif

74 Introduzione al C++ e alla programmazione ad oggetti febbraio Organizzazione dei files (2) –Files sorgente (.C,.cxx,.cpp,.cc ) contengono limplementazione di funzioni e metodi codice eseguibile includono gli header files utilizzando le direttive del preprocessore vengono compilati –Funzioni inline (.icc ) La definizione di una funzione inline deve essere visibile là dove viene usata. Normalmente implementate negli header files o in files separati (con estensione.icc ) che devono essere inclusi nel files sorgente che ne facciano uso

75 Introduzione al C++ e alla programmazione ad oggetti febbraio C++ e Object Orientation Definizione di nuovi tipi (oltre a int, float, double) come: numeri complessi, vettori, matrici,... ma anche: traiettorie, superfici, elementi di apparati sperimentali,... Gli oggetti permettono di modellare una problema che rappresenti la realtà

76 Introduzione al C++ e alla programmazione ad oggetti febbraio … C++ e Object Orientation Object Orientation implementata in C++ attraverso il concetto di classe: I dati privati (o attributi) di una classe definiscono lo stato delloggetto Le funzioni (o metodi) di una classe implementano la risposta ai messaggi

77 Introduzione al C++ e alla programmazione ad oggetti febbraio Una classe C++ Messaggio Metodo Attributo

78 Introduzione al C++ e alla programmazione ad oggetti febbraio Classe Vector2D Un esempio: un vettore bidimensionale class Vector2D { public: Vector2D(double x, double y); double x(); double y(); double r(); double phi(); private: double x_; double y_ }; class Vector2D { public: Vector2D(double x, double y); double x(); double y(); double r(); double phi(); private: double x_; double y_ }; Vector2D.h costruttore funzioni o metodi dati o attributi Punto e virgola! #include Vector2D.h Vector2D::Vector2D(double x, double y): x_(x), y_(y) { } double Vector2D::x() { return x_; } double Vector2D::r() { return sqrt( x_*x_ + y_*y_); }... #include Vector2D.h Vector2D::Vector2D(double x, double y): x_(x), y_(y) { } double Vector2D::x() { return x_; } double Vector2D::r() { return sqrt( x_*x_ + y_*y_); }... Vector2D.cc

79 Introduzione al C++ e alla programmazione ad oggetti febbraio Interfaccia e implementazione #include Vector.h Vector2D::Vector2D(double x, double y) : x_(x), y_(y) {} double Vector2D::x() { return x_; } double Vector2D::r() { return sqrt(x_*x_ + y_*y_); } Vector2D.cc class Vector2D { public: Vector2D(double x, double y); double x(); double y(); double r(); double phi(); private: double x_; double y_; }; Vector2D.h Gli attributi privati non sono accessibili al di fuori della classe I metodi pubblici sono gli unici visibili

80 Introduzione al C++ e alla programmazione ad oggetti febbraio Costruttori e distruttori Un costruttore è un metodo il cui nome è quello della classe a cui appartiene Lo scopo di un costruttore è quello di costruire oggetti del tipo della classe. Questo implica linizializzazione degli attributi e, frequentemente, allocazione di memoria dallo heap Un costruttore la cui lista di argomenti è vuota o composta di argomenti di default viene normalmente chiamato costruttore di default Vector2D::Vector2D() {....} // costruttore di default #include Vector2D.h... Vector2D v; // oggetto costruito con il // costruttore di default

81 Introduzione al C++ e alla programmazione ad oggetti febbraio Costruttori e distruttori (2) Un costruttore del tipo che ha come argomento un riferimento ad un oggetto della stessa classe viene chiamato copy constructor Il copy constructor viene normalmente utilizzato: –quando un oggetto è inizializzato per assegnazione –quando un oggetto è passato come argomento ad una funzione –quando un oggetto è ritornato da una funzione Se non viene fornito esplicitamente dallutente, il compilatore ne genererà uno automaticamente Vector2D::Vector2D(const Vector2D& v) {....} Vector2D v(v1); // dove v1 e` di tipo Vector2D

82 Introduzione al C++ e alla programmazione ad oggetti febbraio Costruttori e distruttori (3) Gli attributi di una classe possono essere inizializzati nel costruttore per mezzo di una lista di inizializzatori, che precede il corpo della funzione Quando uno degli attributi è esso stesso una classe, il costruttore appropriato viene scelto sulla base dei parametri forniti nellinizializzazione E` obbligatorio inizializzare gli attributi (non statici) che siano o riferimenti o const Vector2D::Vector2D(double x, double y) : x_(x), y_(y) {... }

83 Introduzione al C++ e alla programmazione ad oggetti febbraio Costruttori e distruttori (4) Il distruttore è un metodo il cui nome è quello della classe a cui appartiene preceduto da una tilde ( ~ ) Il distruttore viene chiamato automaticamente quando un oggetto sta per essere distrutto (sia perchè delete è stato invocato sia perchè loggetto è finito fuori scope Il compito del distruttore è di assicurarsi che loggetto per cui è invocato verrà distrutto senza conseguenze. In particolare, se memoria è stata allocata nel costruttore, il distruttore dovrà assicurarsi di restituirla allo heap Vector2D::~Vector2D() {}// vuoto, in questo caso

84 Introduzione al C++ e alla programmazione ad oggetti febbraio Costruttori e distruttori (5) I costruttori con un solo parametro sono automaticamente trattati come operatori di conversione Per evitare la conversione si puo` usare explicit Vector2D::Vector2D(int i) {...} // costruisce un vettore a partire da un intero, ma puo` // essere usato per convertire un intero in vettore v=Vector2D(i); explicit Vector2D(int); // solo costruttore

85 Introduzione al C++ e alla programmazione ad oggetti febbraio Classe Vector2D #include #include Vector2D.h int main() { Vector2D v(1, 1); cout << v = ( << v.x() <<, << v.y() << ) << endl; cout << r = << v.r(); cout << phi = << v.phi() << endl; return 0; } #include #include Vector2D.h int main() { Vector2D v(1, 1); cout << v = ( << v.x() <<, << v.y() << ) << endl; cout << r = << v.r(); cout << phi = << v.phi() << endl; return 0; } main.cc Come usare Vector2D : v = (1, 1) r = phi = v = (1, 1) r = phi = Output: invoca il constructor

86 Introduzione al C++ e alla programmazione ad oggetti febbraio Classe Vector2D #include #include Vector2D.h int main() { Vector2D *v = new Vector2D(1, 1); cout << v = ( x() <<, y() << ) << endl; cout r(); cout phi() << endl; delete v; return 0; } #include #include Vector2D.h int main() { Vector2D *v = new Vector2D(1, 1); cout << v = ( x() <<, y() << ) << endl; cout r(); cout phi() << endl; delete v; return 0; } main.cc … oppure attraverso un puntatore... v = (1, 1) r = phi = v = (1, 1) r = phi = Output: Allocazione sullo heap Attenzione!

87 Introduzione al C++ e alla programmazione ad oggetti febbraio Interfaccia e implementazione La struttura interna dei dati ( x_, y_ ) che rappresentano loggetto della classe Vector2D sono nascosti ( private ) agli utilizzatori della classe. Gli utilizzatori non dipendono dalla struttura interna dei dati (come lo erano gli utilizzatori dei common blocks Fortran) Se la struttura interna cambia (es.: r_, phi_ ), il codice che usa Vector2D non deve essere modificato.

88 Introduzione al C++ e alla programmazione ad oggetti febbraio Protezione dellaccesso ai dati: I metodi di una classe hanno libero accesso ai dati privati e protetti di quella classe Classe Vector2D #include #include Vector2D.h int main() { Vector2D v(1, 1); cout << V = ( << v.x_ <<, // << v.y_ <<, << endl; // non compila ! cout << r = << v.r(); cout << phi = << v.phi() << endl; } #include #include Vector2D.h int main() { Vector2D v(1, 1); cout << V = ( << v.x_ <<, // << v.y_ <<, << endl; // non compila ! cout << r = << v.r(); cout << phi = << v.phi() << endl; } main.cc

89 Introduzione al C++ e alla programmazione ad oggetti febbraio Selettore: metodo che non modifica lo stato (attributi) della classe. E dichiarato const Modificatore: metodo che può modificare lo stato della classe Selettori e modificatori #include Vector2D.h void Vector2D::scale(double s) { x_ *= s; y_ *= s; } Vector2D.cc class Vector2D { public: Vector2D(double x, double y); double x() const; double y() const; double r() const; double phi() const; void scale(double s); private: double x_, y_; }; Vector2D.h modificatore #include Vector2D.h int main() { const Vector2D v(1, 0); double r = v.r() // OK v.scale( 1.1 ); // errore! } #include Vector2D.h int main() { const Vector2D v(1, 0); double r = v.r() // OK v.scale( 1.1 ); // errore! } main.cc Selettori ( const )

90 Introduzione al C++ e alla programmazione ad oggetti febbraio friend La keyword friend puo` essere usata perche` una funzione (o una classe) abbia libero accesso ai dati privati di unaltra classe class A {... friend int aFunc(); friend void C::f(int); }; class B { … friend class C; }; class C {... };

91 Introduzione al C++ e alla programmazione ad oggetti febbraio friend (2) friend (nonostante il nome) e` nemico dellincapsulamento e quindi dellObject Orientation Un uso eccessivo di friend è quasi sempre sintomo di un cattivo disegno Esistono anche situazioni in cui un friend può essere accettabile –Overloading di operatori binari –Considerazioni di efficienza –Relazione speciale fra due classi A programmer must confer with an architect before making friend declarations

92 Introduzione al C++ e alla programmazione ad oggetti febbraio static Attributi dichiarati static in una classe sono condivisi da tutti gli oggetti di quella classe Metodi dichiarati static non possono accedere ad attributo non statici della classe Attiributi statici possono essere usati e modificati soltanto da metodi statici Nonostante lutilizzo di static sembri imporre condizioni troppo restrittive, esso risulta utile nellimplementazione di: –contatori –singleton (vedi oltre)

93 Introduzione al C++ e alla programmazione ad oggetti febbraio Un contatore Class MyClass { private: static int counter; static void increment_counter() { counter++; } static void decrement_counter() { counter--; } public: MyClass() { increment_counter(); } ~MyClass() { decrement_counter(); } static int HowMany() { return counter; } }; #include #include MyClass.h int MyClass::counter=0; int main() { MyClass a,b,c; MyClass *p=new MyClass; cout<< How many? << MyClass::HowMany() <

94 Introduzione al C++ e alla programmazione ad oggetti febbraio Un singleton Un singleton è una classe di cui, ad ogni momento nel corso del programma, non può esistere più di una copia (istanza) class aSingleton { private: static aSingleton *ptr; aSingleton () {} public: static aSingleton *GetPointer(){ if (ptr==0) ptr=new aSingleton; return ptr; } }; #include aSingleton.h aSingleton *aSingleton::ptr=0; int main() { aSingleton *mySing= aSingleton::GetPointer();... Return 0; } Pattern utile per limplementazione di classi manager di cui deve esistere una sola istanza Attenzione a non farlo diventare lequivalente di un common block!

95 Introduzione al C++ e alla programmazione ad oggetti febbraio Operatori E possibile ridefinire +, -, *, [], ++, ==,... class Vector2D { public: Vector2D(double x, double y); double x() const; double y() const; double r() const; double phi() const; private: double x_; double y_; }; Vector2D operator+(const Vector2D& v1, const Vector2D& v2); Vector2D operator-(const Vector2D& v1, const Vector2D& v2); class Vector2D { public: Vector2D(double x, double y); double x() const; double y() const; double r() const; double phi() const; private: double x_; double y_; }; Vector2D operator+(const Vector2D& v1, const Vector2D& v2); Vector2D operator-(const Vector2D& v1, const Vector2D& v2); Vector2D.h Vector2D operator+(const Vector2D& v1, const Vector2D& v2) { return Vector2D(v1.x() + v2.x(), v1.y() + v2.y()); } Vector2D operator-(const Vector2D& v1, const Vector2D& v2) { return Vector2D(v1.x() - v2.x(), v1.y() - v2.y()); } Vector2D operator+(const Vector2D& v1, const Vector2D& v2) { return Vector2D(v1.x() + v2.x(), v1.y() + v2.y()); } Vector2D operator-(const Vector2D& v1, const Vector2D& v2) { return Vector2D(v1.x() - v2.x(), v1.y() - v2.y()); } Vector2D.cc

96 Introduzione al C++ e alla programmazione ad oggetti febbraio Operatori (2) Esempio: #include #include Vector2D.h int main() { Vector2D v1(1, 0), v2(0, 1); Vector2D v; v = v1 + v2; cout << v = << v << endl; cout << r = << v.r(); cout << phi = << v.phi() << endl; } #include #include Vector2D.h int main() { Vector2D v1(1, 0), v2(0, 1); Vector2D v; v = v1 + v2; cout << v = << v << endl; cout << r = << v.r(); cout << phi = << v.phi() << endl; } main.cc v = (1, 1) r = theta = Output : ridefinizione di << v.operator=( operator+(v1, v2) ); Sintassi alternativa :

97 Introduzione al C++ e alla programmazione ad oggetti febbraio Operatori (3) Esempio: #include #include Vector3D.h #include Matrix.h // matrice 3x3 int main() { Vector3D v1(1, 1, 0); double phi = M_PI/3; double c = cos(phi), s = sin(phi); Matrix m(1, 0, 0, 0, c, s, 0, -s, c); Vector3D u = m * v; } #include #include Vector3D.h #include Matrix.h // matrice 3x3 int main() { Vector3D v1(1, 1, 0); double phi = M_PI/3; double c = cos(phi), s = sin(phi); Matrix m(1, 0, 0, 0, c, s, 0, -s, c); Vector3D u = m * v; } main.cc greco

98 Introduzione al C++ e alla programmazione ad oggetti febbraio this In una classe è automaticamente definito un attributo particolare: this – this è un puntatore alloggetto di cui fa parte –E particolarmente utile quando si definisce un operatore di assegnazione ( = ): class Vector2D { public: Vector2D& operator=(const Vector2D& ); //... private: double x_, y_; }; class Vector2D { public: Vector2D& operator=(const Vector2D& ); //... private: double x_, y_; }; Vector2D.h Vector2D& operator=(const Vector2D& v){ x_=v.x(); y_=v.y(); return *this; } Vector2D& operator=(const Vector2D& v){ x_=v.x(); y_=v.y(); return *this; } Vector2D.cc #include Vector2D.h int main() { Vector2D null(0, 0); Vector2D a, b; a=b=null; } #include Vector2D.h int main() { Vector2D null(0, 0); Vector2D a, b; a=b=null; } main.cc Loperatore = ritorna una referenza a se stesso. Permette assegnazioni multiple

99 Introduzione al C++ e alla programmazione ad oggetti febbraio Overloading di operatori possono esistere funzioni con lo stesso nome ma con argomenti diversi Non bisogna pero` esagerare! Ogni operatore deve avere un significato ben preciso, per ragioni di chiarezza. class Vector2D { public: //... private: double x_, y_; }; Vector2D operator*(const Vector2D &, double); double operator*(const Vector2D&, const Vector2D&); class Vector2D { public: //... private: double x_, y_; }; Vector2D operator*(const Vector2D &, double); double operator*(const Vector2D&, const Vector2D&); Vector2D.h Vector2D operator*(const Vector2D&, double s) { return Vector2D( v.x() * s, v.y() * s); } double operator*(const Vector2D& v1, const Vector2D& v2) { return ( v1.x() * v2.x() + v1.y() * v2.y() ); } Vector2D operator*(const Vector2D&, double s) { return Vector2D( v.x() * s, v.y() * s); } double operator*(const Vector2D& v1, const Vector2D& v2) { return ( v1.x() * v2.x() + v1.y() * v2.y() ); } Vector2D.cc

100 Introduzione al C++ e alla programmazione ad oggetti febbraio Overloading di operatori (2) Permette di utilizzare tipi definiti dallutente come se fossero tipi fondamentali La cardinalita`, lassociativita` e la precedenza di un operatore non possono essere modificati Operatori unari sono implementati come metodi senza argomenti (loggetto è largomento implicito) Operatori binari possono essere implementati come metodi con un argomento (il primo argomento, implicito, è loggetto il cui operatore agisce) o come funzioni friend a due argomenti.

101 Introduzione al C++ e alla programmazione ad oggetti febbraio Programmazione generica template T max( T p1, T p2 ) { if ( p1 < p2 ) return p2; else return p1; } int main() { Vector v1,v2; cout (10,20) (2.6,1.0) (v1,v2) << endl;} Main.cc Per il tipo T deve essere definito loperatore < Il C++ fornisce un metodo per creare un polimorfismo parametrico. E possibile utilizzare lo stesso codice per tipi differenti: il tipo della variabile diventa un parametro

102 Introduzione al C++ e alla programmazione ad oggetti febbraio Sintassi template function definition template class definition typename Ogni volta che nella definizione della funzione o della classe appare identifier questo viene sostituito dal compilatore con il tipo fornito nella chiamata. La dichiarazione e limplementazione del template devono essere nello stesso file ove il template viene utilizzato

103 Introduzione al C++ e alla programmazione ad oggetti febbraio Parametri interi possono essere inclusi nella dichiarazione del template I parametri di default possono essere tralasciati Parametri templati template class array_n {... private: T items[n]; // n istanziato esplicitamente }; array_n w;// w array di complessi

104 Introduzione al C++ e alla programmazione ad oggetti febbraio Templates di templates Largomento di un template puo` essere esso stesso un template questo permette la creazione e lutilizzo di meta- templates (templates istanziati con templates) molto sofisticati la Standard Template Library fa uso di questa possibilita` template class T3 >

105 Introduzione al C++ e alla programmazione ad oggetti febbraio Funzioni template e parametri Una buona parte dei compilatori accetta una sintassi ristretta per quel che riguarda le funzioni template. ANSI/C++ prevede invece che anche parametri numerici possano essere inclusi nella definizione del template template void swap(T& x, T& y){ T temp; temp=x; x=y; y=temp; } template void swap(T& x, T& y){ T temp; temp=x; x=y; y=temp; } template T aFunc(){ T temp[n];... } template T aFunc(){ T temp[n];... } OK per ogni compilatore ANSI/C++, ma la maggior parte dei compilatori lo rifiuta

106 Introduzione al C++ e alla programmazione ad oggetti febbraio Membri statici Per le classi template, gli attributi statici non sono universali ma specifici di ogni istanza Le variabili statiche MyClass ::counter e MyClass ::counter sono diverse template class MyClass { public: static int counter;... }; MyClass a,b; MyClass c; template class MyClass { public: static int counter;... }; MyClass a,b; MyClass c;

107 Introduzione al C++ e alla programmazione ad oggetti febbraio Un esempio: lo stack di interi val Contenuto next val Contenuto next... val Contenuto next Stack top Stack top Lo stack vuoto class Contenuto {... private: Contenuto* next; int val; }; class Stack {... private: Contenuto* top; }; class Contenuto {... private: Contenuto* next; int val; }; class Stack {... private: Contenuto* top; };

108 Introduzione al C++ e alla programmazione ad oggetti febbraio Un esempio: lo stack di interi class Stack { public: Stack() {top = 0;} ~Stack() {} void push ( int i ) { Contenuto* tmp = new Contenuto(i,top ); top = tmp; } int pop () { int ret = top->getVal(); Contenuto* tmp = top; top = top->getNext(); delete tmp; return ret; } private: Contenuto* top; }; class Stack { public: Stack() {top = 0;} ~Stack() {} void push ( int i ) { Contenuto* tmp = new Contenuto(i,top ); top = tmp; } int pop () { int ret = top->getVal(); Contenuto* tmp = top; top = top->getNext(); delete tmp; return ret; } private: Contenuto* top; }; class Contenuto { public: Contenuto ( int i, Contenuto* ptn ) { val=i; next=ptn; } int getVal (){ return val; } Contenuto* getNext() {return next;} private: Contenuto* next; int val; }; class Contenuto { public: Contenuto ( int i, Contenuto* ptn ) { val=i; next=ptn; } int getVal (){ return val; } Contenuto* getNext() {return next;} private: Contenuto* next; int val; }; int main() { Stack s; s.push ( 10 ); s.push ( 20 ); cout << s.pop() << - << s.pop; return 0; }; int main() { Stack s; s.push ( 10 ); s.push ( 20 ); cout << s.pop() << - << s.pop; return 0; }; User code >> Output

109 Introduzione al C++ e alla programmazione ad oggetti febbraio Lo stack templato template class Stack { public: Stack() {top = NULL;} ~Stack() {;} void push ( T i ) { Contenuto * tmp = new Contenuto (i,top ); top = tmp; } T pop () { T ret = top->getVal(); Contenuto * tmp = top; top = top->getNext(); delete tmp; return ret; } private: Contenuto * top; }; template class Stack { public: Stack() {top = NULL;} ~Stack() {;} void push ( T i ) { Contenuto * tmp = new Contenuto (i,top ); top = tmp; } T pop () { T ret = top->getVal(); Contenuto * tmp = top; top = top->getNext(); delete tmp; return ret; } private: Contenuto * top; }; template class Contenuto { public: Contenuto ( T i, Contenuto* ptn ) { val = i; next = ptn; } T getVal (){ return val; } Contenuto* getNext() {return next;} private: Contenuto* next; T val; }; template class Contenuto { public: Contenuto ( T i, Contenuto* ptn ) { val = i; next = ptn; } T getVal (){ return val; } Contenuto* getNext() {return next;} private: Contenuto* next; T val; }; int main() { Stack s; s.push ( 10 ); s.push ( 20 ); Stack s1; Stack s2; cout << s.pop() << << s.pop; return 0;}; int main() { Stack s; s.push ( 10 ); s.push ( 20 ); Stack s1; Stack s2; cout << s.pop() << << s.pop; return 0;}; User code

110 Introduzione al C++ e alla programmazione ad oggetti febbraio La Standard Template Library vettori, liste, mappe, …. find, replace, reverse, sort, …. puntatori intelligenti La libreria standard STL e una libreria di classi di contenitori, algoritmi ed iteratori. STL e una libreria generica: tutti i suoi componenti sono parametrizzati mediante lutilizzo dei template

111 Introduzione al C++ e alla programmazione ad oggetti febbraio Gli iteratori sono dei puntatori agli elementi di un contenitore e ci permettono di muoverci allinterno di esso: –Iteratori monodirezionali: Permettono di accedere allelemento successivo o al precedente –Iteratori bidirezionali : Permettono di accedere sia allelemento successivo che al precedente –Iteratori ad accesso casuale : Permettono di accedere ad un qualunque elemento del contenitore Iteratori (puntatori intelligenti)

112 Introduzione al C++ e alla programmazione ad oggetti febbraio Un contenitore è un oggetto capace di immagazzinare altri oggetti e che possiede metodi per accedere ai suoi elementi. –Ogni contenitore ha un iteratore associato che permette di muoversi tra gli elementi contenuti –Una sequenza è un contenitore di lunghezza variabile i cui elementi sono organizzati linearmente. E possibile aggiungere e rimuovere elementi –Un contenitore associativo è una sequenza che permette un efficiente accesso ai suoi elementi basato su una chiave. Contenitori

113 Introduzione al C++ e alla programmazione ad oggetti febbraio Sequenze vector –Tempo costante di inserimento e cancellazione di elementi allinizio e alla fine del vettore. –Tempo lineare con il numero di elementi per inserimento e cancellazione di elementi allinterno del vettore –Iteratore ad accesso casuale list –Tempo costante di inserimento e cancellazione di elementi in ogni punto della lista –Iteratore bidirezionale

114 Introduzione al C++ e alla programmazione ad oggetti febbraio vector begin() end() end() p pp p p 0 push_back() p ++ Le locazioni di memoria sono contigue –Accesso casuale, veloce laccesso agli elementi, lenti inserimento ed estrazione

115 Introduzione al C++ e alla programmazione ad oggetti febbraio val nodo next prev list Simile allo stack, ma consente di muoversi in due direzioni Le locazioni di memoria non sono contigue –Lenta la ricerca, veloci inserimento ed estrazione... list top val nodo next prev val nodo next prev bottom

116 Introduzione al C++ e alla programmazione ad oggetti febbraio Contenitori associativi Sono contenitore di coppie ( key, value ) e possiedono un iteratore bidirezionale map –Viene richiesto loperatore < per la chiave –Gli elementi sono ordinati secondo la chiave

117 Introduzione al C++ e alla programmazione ad oggetti febbraio Algoritmi Gli algoritmi sono delle funzioni globali capaci di agire su contenitori differenti Sono incluse operazioni di ordinamento (sort, merge, min, max...), di ricerca (find, count, equal...), di trasformazione (transform, replace, fill, rotate, shuffle...), e generiche operazioni numeriche (accumulate, adjacent difference...). find count copy fill sort min, max

118 Introduzione al C++ e alla programmazione ad oggetti febbraio #include int main() { container; int val; for (int i=0; i<10; i++) { val = (int)((float)rand()/RAND_MAX*10); container.push_back(val); } ::iterator it1; for ( it1=container.begin(); it1!=container.end(); it1++) cout << "vector : " << *it1 << endl; return 0; } Esempio uso sequenze vector list

119 Introduzione al C++ e alla programmazione ad oggetti febbraio #include int main() { map amap; amap["Primo]=1; amap[Secondo]=2; cout << "Size : " << amap.size() << endl; amap["Terzo"]=3; amap["Quarto"]=4; cout << "Size : " << amap.size() << endl; map ::iterator it; for ( it=amap.begin(); it!=amap.end(); it++) cout first second << endl; cout second << endl; return 0; } #include int main() { map amap; amap["Primo]=1; amap[Secondo]=2; cout << "Size : " << amap.size() << endl; amap["Terzo"]=3; amap["Quarto"]=4; cout << "Size : " << amap.size() << endl; map ::iterator it; for ( it=amap.begin(); it!=amap.end(); it++) cout first second << endl; cout second << endl; return 0; } Esempio uso contenitori associativi

120 Introduzione al C++ e alla programmazione ad oggetti febbraio Assegnazione di un metodo ad un messaggio I metodi pubblici di una classe costituiscono linterfaccia della classe (cioè i messaggi che loggetto può interpretare) La funzione è assegnata al messaggio in fase di codifica (early binding) Può essere necessario assegnare la funzione al messaggio a run-time (late binding) Polimorfismo

121 Introduzione al C++ e alla programmazione ad oggetti febbraio Controllo dei tipi Controllare i tipi significa verificare che ad un oggetto vengano inviati solo messaggi che è in grado di comprendere: –controllo del nome del metodo –controllo della lista degli argomenti In C++ il controllo è fatto dal compilatore (strong typing) In altri linguaggi (ad esempio SmallTalk) è fatto a run-time (weak typing)

122 Introduzione al C++ e alla programmazione ad oggetti febbraio Typing & Binding Typing Definizione dei messaggi e degli argomenti Binding Assegnazione di un metodo ad un messaggio Strong Consistenza dei tipi verificata dal compilatore Weak Consistenza dei tipi verificata a run-time Early In fase di programmazione INFLESSIBILE Late A run-time POLIMORFISMO

123 Introduzione al C++ e alla programmazione ad oggetti febbraio Esempio: i soldati Tutti i soldati devono capire il messaggio attacca. Il messaggio ha conseguenze diverse a seconda del tipo di soldato: –un arcere lancia una freccia –un fante usa la spada –un cavaliere lancia una lancia Il gestore della schermata vuole tenere una lista di soldati e vuole poter dire ad ogni soldato di attaccare indipendentemente dal tipo ma basandosi solo sulla posizione.

124 Introduzione al C++ e alla programmazione ad oggetti febbraio list lista; riempiLista(lista); Posizione unaPosizione=...; list ::iterator iter; for(iter=lista.begin();iter!=lista.end();iter++){ Soldato unSoldato=(*iter); if(unSoldato.posizione()==unaPosizione) unSoldato.attacca(); } class Soldato { void attacca() { // cosa scrivo qui?!? Per quale tipo di // soldato implemento il metodo attacca()? } }; list lista; riempiLista(lista); Posizione unaPosizione=...; list ::iterator iter; for(iter=lista.begin();iter!=lista.end();iter++){ Soldato unSoldato=(*iter); if(unSoldato.posizione()==unaPosizione) unSoldato.attacca(); } class Soldato { void attacca() { // cosa scrivo qui?!? Per quale tipo di // soldato implemento il metodo attacca()? } };

125 Introduzione al C++ e alla programmazione ad oggetti febbraio Polimorfismo Polimorfismo con tipi controllati dal compilatore (Strong typing & late binding). Come? In C++ viene implementato tramite il concetto di ereditarietà (inheritance) Classe astratta: definisce i messaggi Classe concreta: assegna i metodi ai messaggi La classe concreta eredita da quella astratta

126 Introduzione al C++ e alla programmazione ad oggetti febbraio Ereditarietà Una classe può essere derivata da una classe esistente usando la sintassi: –public, protected e private specificano il tipo di accesso ai membri della classe Se la classe base non ha un costruttore di default: –La classe derivata deve implementarlo Se la classe base ha un costruttore di default: –il costruttore della classe derivata deve esplicitamente invocarlo nella sua lista di inizializzatione Il costruttore della classe base può così essere eseguito prima che il costruttore della classe derivata sia eseguito class newclass: (public|protected|private) oldclass { dichiarazioni... };

127 Introduzione al C++ e alla programmazione ad oggetti febbraio Ereditarietà (2) Una classe derivata pubblicamente è a tutti gli effetti un sottotipo della classe base. –Un oggetto della classe derivata può essere trattato come se fosse un oggetto della classe base –Un puntatore alla classe base può puntare ad oggetti della classe derivata –Un riferimento alla classe derivata può, se la cosa ha un senso, essere implicitamente convertito ad un riferimento alla classe base –E` possibile dichiarare un riferimento alla classe base ed inizializzarlo ad un oggetto della classe derivata

128 Introduzione al C++ e alla programmazione ad oggetti febbraio Ereditarietà (3) La definizione dellinterfaccia (metodi pubblici) della classe base è estremamente importante perchè determina il comportamento delle classi derivate Un metodo della classe base può essere: –dichiarato e definito normalmente la classe derivata eredita questo metodo e NON può ridefinirlo –dichiarato virtual e definito normalmente la classe derivata eredita questo metodo e può ridefinirlo –dichiarato virtual e non definito (=0) la classe derivata eredita il metodo e DEVE ridefinirlo

129 Introduzione al C++ e alla programmazione ad oggetti febbraio Classi base astratte Una funzione puramente virtuale è un metodo virtuale non definito. E` dichiarato come: Una classe che ha almeno un metodo puramente virtuale è chiamata classe astratta Oggetti di una classe astratta non possono esistere Puntatori ad una classe base astratta possono essere definiti ed usati polimorficamente (per puntare ad oggetti delle classi derivate) Una classe base astratta viene introdotta per specificare linterfaccia di una categoria di classi virtual func_prototype = 0;

130 Introduzione al C++ e alla programmazione ad oggetti febbraio class Soldato { virtual void attacca()=0; }; class Arcere : public Soldato { virtual void attacca() { // lancia una freccia } }; class Fante : public Soldato { virtual void attacca() { // usa la spada } };... class Soldato { virtual void attacca()=0; }; class Arcere : public Soldato { virtual void attacca() { // lancia una freccia } }; class Fante : public Soldato { virtual void attacca() { // usa la spada } };...

131 Introduzione al C++ e alla programmazione ad oggetti febbraio Erediarietà multipla Lereditarietà multipla permette di derivare una classe da due o più classi base. La sintassi viene estesa per permettere una lista di classi base L ereditarietà multipla viene spesso utilizzata per combinare uninterfaccia ed una implementazione, ma è molte volte sintomo di un cattivo disegno class A {.. }; class B {.. }; class AplusB: public A, private B {.. };

132 Introduzione al C++ e alla programmazione ad oggetti febbraio class Base {....// base implementation }; class Derived: public Base {.. void new_method() ; // non e definito in Base! }; void func(Base *ptr) // ptr e un obbetto dell classe Base { ptr->new_method(); // Errore!!! Derived *p = dynamic_cast (ptr) if (p !=0) { p->new_method(); } dynamic_cast dynamic_cast opera una conversione, se è possibile, fra due tipi. Il puntatore ritornato NON è nullo soltanto se il tipo delloggetto su cui si opera è quello che ci si aspetta

133 Introduzione al C++ e alla programmazione ad oggetti febbraio Ereditarietà (4) Una classe derivata estende la classe base e ne eredita tutti i metodi e gli attributi class Track { public: LorentzVector momentum() { return p_; } protected: LorentzVector p_; }; class Track { public: LorentzVector momentum() { return p_; } protected: LorentzVector p_; }; Track.h #include Track.h class DchTrack : public Track { public: int hits() { return hits_->size(); } DchHit* hit(int n) { return hits_[n]; } protected: list hits_; }; #include Track.h class DchTrack : public Track { public: int hits() { return hits_->size(); } DchHit* hit(int n) { return hits_[n]; } protected: list hits_; }; DchTrack.h DchTrack è una Track che ha degli attributi in più ( hits_ ) e nuovi metodi ( DchHit* hit(int n), int hits() )

134 Introduzione al C++ e alla programmazione ad oggetti febbraio Esempio: shape Tutti gli oggetti nella finestra hanno comportamenti comuni che possono essere considerati in astratto: –disegna –sposta –ingrandisc –etc...

135 Introduzione al C++ e alla programmazione ad oggetti febbraio Cerchi e quadrati Quadrato Cerchio

136 Introduzione al C++ e alla programmazione ad oggetti febbraio Circle.h CerchioCostruttore 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

137 Introduzione al C++ e alla programmazione ad oggetti febbraio Cerchio (2) # 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, color_, FILL); } 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

138 Introduzione al C++ e alla programmazione ad oggetti febbraio Quadrato class Square { public: Square(const Point2d&, const Point2d&, Color color = TRASPARENT); ~Square(); void moveAt( const Point2d& p ); void moveBy( const Point2d& p ); void changeColor( Color color ); void scale( double s ); void rotate( double phi ); void draw() const; void cancel() const; private: Point2d center_; Vector2d centerToUpperCorner_; Color color_; }; 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, color_, FILL); } void Square::rotate( double phi ) { cancel(); centerToUpperCorner_.rotate( phi ); draw(); } Square::Square(const Point2d& lowerCorner, const Point2d& upperCorner, Color color) : center_( median(lowerCorner, upperCorner) ), centerToUpperCorner_( upperCorner - center_ ), color_( color ) { draw(); } void Square::scale( double s ) { cancel(); centerToUpperCorner_ *= s; draw(); } Square.cc upperCorner loweCorner centerToUpperCorner _

139 Introduzione al C++ e alla programmazione ad oggetti febbraio 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

140 Introduzione al C++ e alla programmazione ad oggetti febbraio Polimorfismo Tutte le Shapes hanno la stessa interfaccia: draw, pick, move, fillColor..., ma ogni sottotipo diverso può avere la usa personale implementazione

141 Introduzione al C++ e alla programmazione ad oggetti febbraio class Shape { public: Shape() { } virtual ~Shape() { } virtual void moveAt(const Point2d& where) = 0; virtual void changeColor(Color newColor) = 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[ 20 ]; 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 < 20; i++ ) shapes[ i ]->draw(); return 0; } Main.cc

142 Introduzione al C++ e alla programmazione ad oggetti febbraio Ereditarietà e riuso del codice Class CenteredShape: public Shape { public: CenteredShape(Point2d c, Color color = TRASPARENT) : center_(c), color_(color) { /*draw();*/ } ~Circle() { /*cancel();*/ } void moveAt( const Point2d& ); void moveBy( const Vector2d& ); void changeColor( Color ); virtual void scale( double ) = 0; virtual void rotate( double ) = 0; virtual void draw() const = 0; virtual void cancel() const = 0; protected: Point2d center_; Color color_; }; 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, Color col = TRASPARENT) : CenteredShape( median(lowerCorner, upperCorner), col), 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

143 Introduzione al C++ e alla programmazione ad oggetti febbraio Attenzione alle generalizzazioni... class Rectangle { public: Rectangle(double x0, double y0, double lx, double ly) : lx_(lx), ly_(ly), x0_(x0), y0_(y0) { } void scaleX(double s); void scaleY(double s); protected: double x0_, y0_; double lx_, ly_; }; Rectangle.h Attenzione: scegliere le relazioni di ereditarietà può essere non banale. Un quadrato è un rettangolo? class Square : public Rectangle { public: Square(double x0, double y0, double l) : Rectangle(x0, y0, l, l) { } }; Square.h Avere lx_ e ly_ è ridondante per Square Cosa succede se si invoca scaleX o scaleY ? Avere lx_ e ly_ è ridondante per Square Cosa succede se si invoca scaleX o scaleY ?

144 Introduzione al C++ e alla programmazione ad oggetti febbraio Ereditarietà multipla Una classe può ereditare da più classi class DrawableObj { public: virtual void draw() = 0; }; DrawableObj.h class Shape { public: virtual void scale(double s) = 0; virtual void moveAt( Vector2d& ) = 0; }; Shape.h class DrawableShape : public DrawableObj, public Shape { public: virtual void draw(); virtual void scale(double s); virtual void moveAt( Vector2d& ); }; DrawableShape.h

145 Introduzione al C++ e alla programmazione ad oggetti febbraio Strategie di sviluppo di un progetto Requisiti: cosa lutente vuole Analisi: la visione dellinformatico dei requisiti Disegno: laspetto del sistema software Produzione: codifica Testing: debugging e verifica dei requisiti Mantenimento: installazione del prodotto e controllo del funzionamento per il resto della sua vita

146 Introduzione al C++ e alla programmazione ad oggetti febbraio Modello a cascata Analisi Disegno Produzione Testing Requisiti

147 Introduzione al C++ e alla programmazione ad oggetti febbraio Modello evoluzionario Requisiti Analisi Disegno Produzione Testing

148 Introduzione al C++ e alla programmazione ad oggetti febbraio Confronto fra i modelli di sviluppo A cascata Processo lineare (si torna al passo precedente solo in caso di problemi) Confinamento delle attività in ogni fase Facile da gestire (gestione delle scadenze) Difficile da modificare Prodotto utilizzabile solo alla fine del processo Evoluzionario Processo ciclico (brevi processi completi) Attività distribuite su più fasi Difficile da gestire Facile da modificare e integrare Prototipo utilizzabile fin dal primo ciclo

149 Introduzione al C++ e alla programmazione ad oggetti febbraio Requisiti Definizione delle richieste da parte dellutente del programma (o di una sua parte) sul sistema Si parla di programmazione per contratto perchè lutente richiede solamente la definizione del servizio richiesto NON la metodologia seguita per fornirglielo –è possibile delegare parte del lavoro richiesto ad altri –il sistema è indipendente da chi è il suo utente INCAPSULAMENTO!

150 Introduzione al C++ e alla programmazione ad oggetti febbraio Analisi Comprensione e razionalizzazione delle richieste dellutente Costruzione di un modello –astrazione (semplificazione delle relazioni) –rilevanza (identificazione degli oggetti chiave) Da non trascurare: analisi delle soluzioni esistenti. Può far risparmiare molto tempo!!!

151 Introduzione al C++ e alla programmazione ad oggetti febbraio Disegno Definizione delle interfacce Definizione di oggetti e classi Definizione degli stati e dellimplementazione Definizione delle relazioni

152 Introduzione al C++ e alla programmazione ad oggetti febbraio Disegno (2) Dopo ogni ciclo bisogna analizzare i rischi, la stabilità del disegno e la complessità delle classi Se una classe è troppo complessa conviene dividerla Ad ogni ciclo il numero di modifiche deve diminuire Architetture troppo complesse devono essere modularizzate

153 Introduzione al C++ e alla programmazione ad oggetti febbraio Codifica Cè poco da dire… Non sopravvalutate questa fase:

154 Introduzione al C++ e alla programmazione ad oggetti febbraio Testing Debugging: è ovvio… il codice non deve dare errori. Use cases: specificano il comportamento del sistema in una regione. Scenarios: sono esempi concreti di use cases. Per definizione se tutti gli scenari sono soddisfatti correttamente il test è positivo.

155 Introduzione al C++ e alla programmazione ad oggetti febbraio Metodi di sviluppo del software Un metodo comprende: Una notazione mezzo comune per esprimere strategie e decisioni Un processo specifica come deve avvenire lo sviluppo

156 Introduzione al C++ e alla programmazione ad oggetti febbraio Metodi Object Oriented –Booch Method by Grady Booch –OMT by Jim Rumbaugh –Objectory (Use Cases) by Ivar Jacobson –CRC by R.Wirfs-Brock Di recente introduzione: UML –uno standard OMG (Object Management Group), dal novembre 1997 Grady Booch Jim Rumbaugh Ivar Jacobson

157 Introduzione al C++ e alla programmazione ad oggetti febbraio UML per lanalisi e il disegno Class Diagrams: aspetto statico del sistema. Classi con attributi e metodi e relazioni tra di esse. Sequence e collaboration digrams: comportamento dinamico del sistema. Sequenza dei messaggi scambiati fra gli oggetti. Use case diagrams: illustra gli use cases, le relazioni fra di essi e gli attori che vi partecipano. State diagrams: descrive gli stati in cui ogni oggetto si può trovare e le modalità con cui passa da uno stato allaltro

158 Introduzione al C++ e alla programmazione ad oggetti febbraio Concetti delle classi rivisitati Relazioni tra oggetti Decomposizione funzionale allinterno di una classe –responsabilità dei metodi Decomposizione funzionale tra più classi –responsabilità delle classi

159 Introduzione al C++ e alla programmazione ad oggetti febbraio Rappresentazione delle classi Nome + metodo(arg) # metodo(arg) - metodo(arg) - dato operatori attibuti pubblico protetto privato

160 Introduzione al C++ e alla programmazione ad oggetti febbraio Rappresentazione di una classe C++ in UML class Nome { private: Tipo1 variabile1; Tipo2 variabile2; Tipo3 variabile3; public: Nome(); ~Nome(); Tipo4 funzione1 ( arg ); protected: Tipo5 funzione2 ( arg ); private: Tipo6 funzione3 ( arg ); }; Nome.h Nome - variabile1:Tipo1 - variabile2:Tipo2 - variabile3:Tipo3 + funzione1(arg):Tipo4 # funzione2(arg):Tipo5 - funzione3(arg):Tipo6

161 Introduzione al C++ e alla programmazione ad oggetti febbraio Attributi e metodi Publico ( + ) Privato ( - ) Protetto ( # ) Notazione di Rational Rose

162 Introduzione al C++ e alla programmazione ad oggetti febbraio Principali relazioni fra classi associazione aggregazione by reference (il composito non vive senza il componente) aggregazione by value (aggregazione fisica: esistenza contemporanea) dipendenza generalizzazione (inheritance)

163 Introduzione al C++ e alla programmazione ad oggetti febbraio Aggregazione (contenimento) By reference (condivisa) un autista guida più automobili By value (possesso) una automobile possiede il suo motore

164 Introduzione al C++ e alla programmazione ad oggetti febbraio Cardinalità e direzionalità Il punto non conosce i poligoni Il poligono è costituito da punti Non navigabile

165 Introduzione al C++ e alla programmazione ad oggetti febbraio Dipendenza Non cè nessuna associazione Cè comunque relazione di uso Il CD non conosce il CDPlayer Il CDPlayer usa il CD: se cambia il formato del CD il CDPlayer deve essere modificato

166 Introduzione al C++ e alla programmazione ad oggetti febbraio Generalizzazione (ereditarietà) Ereditarietà virtuale!

167 Introduzione al C++ e alla programmazione ad oggetti febbraio Class Diagram di Shape

168 Introduzione al C++ e alla programmazione ad oggetti febbraio Class Diagram

169 Introduzione al C++ e alla programmazione ad oggetti febbraio Class Diagram

170 Introduzione al C++ e alla programmazione ad oggetti febbraio Object Sequence Diagram

171 Introduzione al C++ e alla programmazione ad oggetti febbraio Object Collaboration Diagram

172 Introduzione al C++ e alla programmazione ad oggetti febbraio CRC Classi, Responsabilità, Collaborazioni C D E F B A xyxy zszs f q p w

173 Introduzione al C++ e alla programmazione ad oggetti febbraio Assegnare Responsabilità Identificare i protagonisti Analizzare il ruolo dei vari oggetti Concentrarsi sul comportamento non la rappresentazione Cercare Oggetti con proprietà comuni: –appartiene a classi diverse, o sono solo oggetti diversi? Definire le interfacce (le operazioni che soddisfano le responsabilità) Una corretta assegnazione delle responsabilità è la chiave di una buona modularità e riuso

174 Introduzione al C++ e alla programmazione ad oggetti febbraio Collaborazione tra classi Le responsabilità vanno suddivise tra i vari oggetti del sistema non deve esistere un controllo centralizzato Un oggetto deve compiere le proprie responsabilità e delegare ad altri operazioni specifiche –Legge di Demeter: non usate oggetti lontani: Invece di: traiettoria.listapunti().aggiungi(Punto); usare: traiettoria.aggiungiPunto(Punto);

175 Introduzione al C++ e alla programmazione ad oggetti febbraio Identificare Relazioni Cercare collaborazioni Cercare aggregazioni Cercare generalizazioni Come un client conosce il suo service provider?

176 Introduzione al C++ e alla programmazione ad oggetti febbraio Relazioni Logiche Generalizazione: Is-a Aggregazione: Has Dipendenza: Knows Implementazione Inheritance Template instantiation Composizione by value Composizione by reference {

177 Introduzione al C++ e alla programmazione ad oggetti febbraio Avere o essere? Uno dei punti critici è distinguere se il rapporto fra due oggetti è del tipo avere o essere: –Un LorentzVector è un Vector o ha un Vector? –Una Traccia è un vector o ha un vector ? –Un Rivelatore è una Superficie o ha una superficie? Per risolvere il problema bisogna guardare a cosa fanno!

178 Introduzione al C++ e alla programmazione ad oggetti febbraio Principio di Liskov Gli oggetti figli possono essere usati ovunque loggetto genitore è richiesto –usare linheritance quando è richiesto il polimorfismo –Non cambiare il comportamento della base class

179 Introduzione al C++ e alla programmazione ad oggetti febbraio Composizione by value o by refrence In C++ la scelta fra aggregazione by value o by refrence può seguire questo schema: –Tipi semplici (int, float, …): by value –Parte dello stato delloggetto: by value –Oggetti condivisi: by reference –Assegnati a run time: by reference Oggetti condivisi by reference: attenzione a chi ha la responsabilità di crearli e cancellarli! (1 new 1 delete!)

180 Introduzione al C++ e alla programmazione ad oggetti febbraio Approccio Outside-in Il corretto approccio è quello di guardare il sistema dallesterno. Identificare prima di tutto gli oggetti che interagiscono con lutente esterno e i messaggi a cui devono saper rispondere (think client!) In seguito identificare gli oggetti che forniscono servizi a questi ultimi e così via Gli algoritmi vengono per ultimi!!!

181 Introduzione al C++ e alla programmazione ad oggetti febbraio CRC Workshop Metodo per la definizione si una architettura bilanciata Ogni partecipante svolge il ruolo di una classe. –Individuazione delle classi –Contrattazione delle responsabilità –Definizione delle collaborazioni –Difesa dal tentativo di assegnazione di responsabilità contrarie alla natura della classe

182 Introduzione al C++ e alla programmazione ad oggetti febbraio Regole per il CRC workshop Tentate di rifuutare le responsabilità –Dovrei? (Non sono io che lo devo fare!) –Potrei? (Non ho i mezzi, o lo stato per farlo!) Cercate di fare poco lavoro –Se avete dovuto accettare una responsabilità cercate di far fare il lavoro a qualcunaltro Potenziate i collaboratori, non interferite

183 Introduzione al C++ e alla programmazione ad oggetti febbraio Design Patterns Sono elementi di software OO riutilizzabile Piccoli insiemi di classi che collaborano implementando dei comportamenti tipici –Creational patterns –Structural patterns –Behavioral patterns I principali sono raccolti in un libro: E. Gamma et al., Design Patterns

184 Introduzione al C++ e alla programmazione ad oggetti febbraio Factory I client possono richiedere la creazione di un prodotto senza dipendervi La Factory dipende dai prodotti concreti, mentre i client dipendono solo da quelli astratti

185 Introduzione al C++ e alla programmazione ad oggetti febbraio Proxy Una richiesta da un client a un server, può essere mediata dal Proxy, che può compiere anche altre operazioni (I/O, caching, etc.)

186 Introduzione al C++ e alla programmazione ad oggetti febbraio Composite Il client può trattare componenti e compositi usando la stessa interfaccia. La composizione può essere ricursiva. Esempio: programmi di grafica

187 Introduzione al C++ e alla programmazione ad oggetti febbraio Gruppo di Shapes Circle, Square,... draw( ) Shape draw( ) GroupofShapes draw( ) 1..* Client _components Il gruppo di shapes è il Composite La shape è il Component Le shapes concrete (Circle, Square, ecc...) sono le Leaf

188 Introduzione al C++ e alla programmazione ad oggetti febbraio #include Shape.h class Circle: public Shape { public: Circle(Point2D c, double r): Shape(), center_(c), radius_(r) {} void draw() const { ; // draw circle } // altri metodi definiti per Circle private: double radius_; Point2D center_; }; Circle.h Codice del modello composite class Shape { public: Shape() {} virtual void draw() const = 0; // altri metodi virtuali ( = 0 ) }; Shape.h

189 Introduzione al C++ e alla programmazione ad oggetti febbraio Codice del modello composite #include Shape.h class GroupofShapes : public Shape { public: typedef vector Container; typedef Container::const_iterator Iterator; GroupofShapes(){} void draw() const { Iterator p=components.begin(); Iterator pe=components.end(); while (p!=pe) { (*p)->draw(); p++; } return; } // gli altri metodi sono definiti operando // sui componenti protected: Container components; }; GroupofShapes.h

190 Introduzione al C++ e alla programmazione ad oggetti febbraio Strategy Il pattern Strategy permette di scegliere lalgoritmo da eseguire a run- time. Nuovi algoritmi possono essere introdotti senza modificare il codice utente.

191 Introduzione al C++ e alla programmazione ad oggetti febbraio Observer Lo stato dell Observer dipende dallo stato del Subject. Il Subject notifica a tutti gli Observer registrati che il suo stato è cambiato.

192 Introduzione al C++ e alla programmazione ad oggetti febbraio Appendice: strighe C-style Le variabili carattere sono gestite come array di char (un char contiene un solo carattere) –accesso agli elementi tramite la sintassi degli array –carattere nullo usato come terminatore ( \0 ) Funzoni di libreria per la gestione dei char* : –#include per utilizzarle –int strlen(const char*); lunghezza della stringa –int strcmp(const char*, const char*); confronto di due stringhe –char* strcpy(char*, const char*); copia la seconda stringa nella prima

193 Introduzione al C++ e alla programmazione ad oggetti febbraio Appendice: la classe string Per semplificare la gestione delle stringhe è stata creata la classe string –#include per usarla –Definiti gli operatori standard: = per lassegnazione + e += per la concatenazione == e tutti gli altri operatori relazionali per il confronto [] per laccesso agli elementi –Disponibile sintassi simile a quella dei contenitori STL: iteratori: string::iterator e string::const_iterator funzioni begin(), end(), size(), ecc... –Interoperabilità con char* : char* c=Pippo; string s=c; char* c1 = s.c_str(); s += c;

194 Introduzione al C++ e alla programmazione ad oggetti febbraio Confronto stringhe C-style e string #include int main(){ int err=0;int big= ; char* c1=LLLong string; for(int i=0;i

195 Introduzione al C++ e alla programmazione ad oggetti febbraio Appendice:operazioni di I/O Si utilizza la libreria iostream –Gli operatori di stream >> e << dirigono il flusso da/per le unità desiderate: cout : standard output. Si sono già visti molti esempi cerr : standard error. Si usa come cout cin : standard input (normalmente la tastiera) include int main(){ string nome; cout << Come ti chiami? << endl; cin >> nome; // Notare la direzione!!! if(nome.empty()) cerr << Stringa nulla! << endl; else cout << Ciao << nome << ! << endl; return 0; }

196 Introduzione al C++ e alla programmazione ad oggetti febbraio Overloading degli operatori di I/O Gli operatori > possono essere ridefiniti per consentire operazioni del tipo: Vector2D v(1,2); cout << Il vettore v vale << v << endl; Si utilizza una funzione friend : class Vector2D { friend ostream& operator <<(ostream& os, const Vector2D v); [...] } ostream& operator <<(ostream& os, const Vector2D v){ os << ( << v.x() <<, << v.y() << );} Si ottiene: Il vettore v vale (1,2)

197 Introduzione al C++ e alla programmazione ad oggetti febbraio Appendice: I/O con files E possibile definire altre unità di I/O –Si utilizza la libreria fstream (include iostream ) –I files di input sono dichiarati ifstream –I files di output sono dichiarati ofstream –I files di input/output sono dichiarati fstream –Costruttore con argomento const char* (nome file) #include int main(){ ifstream fin(file1.dat); // deve esistere! if(!fin){ cerr << file1.dat non esiste << endl; return -1; } ofstream fout(file2.dat); // se esiste viene sovrascritto int i=0; string parola; while (inf >> parola) fout << La << ++i << -esima parola e\ << parola << endl; fin.close(); fout.close(); return 0; }

198 Introduzione al C++ e alla programmazione ad oggetti febbraio Appendice: I/O in memoria E possibile definire unità di I/O in memoria (non legate a files) –Si utilizza la libreria sstream (include iostream ) –Le unità di input sono dichiarati istringstream –Le unità di output sono dichiarati ostringstream –Le unità di input/output sono dichiarati stringstream –I costruttori non hanno argomento –Il metodo str() applicato ad un oggetto di questo tipo ritorna la stringa ( string ) contenuta nellunità: ostringstream messaggio; messaggio << Ciao! << endl; string s=messaggio.str();

199 Introduzione al C++ e alla programmazione ad oggetti febbraio Appendice: Manipolatori di I/O Modificano il comportamento di una stream. boolalpha : true e false rappresentati come stringhe noboolalpha : true e false rappresentati come 1 e 0 (default) showbase : interi stampati col prefisso che indica la base noshowbase : interi stampati senza il prefisso (default) showpoint : floating point stampati sempre col punto decimale noshowpoint : stampa i floating point come interi se non frazionari (default) showpos : stampa + per numeri positivi noshowpos : non stampa + per i numeri positivi (default) skipws: salta gli spazi bianchi in input (default) noskipws : non salta gli spazi bianchi in input uppercase : stampa 0X in esadecimale, E in scientifica lowercase : stampa 0x oppure e (default) dec : interi in base 10 (default) hex : interi in base 16 oct: interi in base 8

200 Introduzione al C++ e alla programmazione ad oggetti febbraio Appendice: Manipolatori di I/O (2) I seguenti manipolatori richiedono: #include left : aggiunge caratteri di riempimento alla destra del val. right : aggiunge caratteri di riempimento alla sinistra internal : aggiunge caratteri fra segno e valore fixed : floating point in notazione decimale (default) scientific : floating point in notazione scientifica flush : svuota il buffer ends : aggiunge il carattere nullo ( \0 ) e svuota il buffer endl : aggiunge un newline e svuota il buffer ws : mangia gli spazi bianchi setfill(ch) : definisce il carattere di riempimento setprecision(n) : definisce la precisione per i floating point setw(n) : scrive o legge in n caratteri setbase(b) : interi in base b

201 Introduzione al C++ e alla programmazione ad oggetti febbraio Esempio di I/O con manipolatori Non tutti i compilatori supportano tutti i manipolatori!!! #include int main() { cout << "inserisci un numero: "; double num=0; while(cin >> num) { int pi = (int)(num); cout << setfill('0') << setprecision(5); cout << "Il numero inserito e\' " << num << endl; cout << "La parte intera e\' " << pi << "(" << hex << setw(6) << pi << " esadecimale)" << dec << endl; cout << "La parte frazionaria e\' " << num-pi << endl; cout << "inserisci un numero: "; } return 0; } inserisci un numero: Il numero inserito e' La parte intera e' 12345( esadecimale) La parte frazionaria e' inserisci un numero:

202 Introduzione al C++ e alla programmazione ad oggetti febbraio Per saperne di più sugli elementi di base del linguaggio C++ **** Lippman, Lajoye, The C++ Primer, 3rd Edition - Addison Wesley *** Pohl, Object-Oriented Programming Using C++, 2nd Edition - Addison Wesley *** Stroustrup, The C++ Programming Language, 3rd Edition - Addison Wesley su trucchi e tranelli in C++ **** Myers, Effective C++, Addison Wesley **** Myers, More Effective C++, Addison Wesley *** Coplien, Advanced C++, Addison Wesley su STL **** Glass, Schuchert, The STL, Prentice Hall *** Ammeraal, Wiley, STL for C++ Programmers - ** Musser, Saini, STL Tutorial and Reference Guide, Addison Wesley

203 Introduzione al C++ e alla programmazione ad oggetti febbraio Per saperne di più (2) su OO A&D *** Booch, Object-Oriented Analysis and Design with Applications, Benjamin/Cummings *** Booch, Object Solutions, Addison Wesley su UML **** Fowler, Scott, UML Distilled, Addison Wesley *** Booch, Rumbaugh, Jacobson, The Unified Modeling Language User Guide, Addison Wesley sui Design Patterns *** Gamma, Helm, Johnson, Vlissides, Design Patterns, Addison Wesley


Scaricare ppt "Introduzione al C++ e alla programmazione ad oggetti Introduzione al C++ e alla programmazione ad oggetti Corso Specialistico CNTC Bologna, 19-23 febbraio."

Presentazioni simili


Annunci Google