Introduzione al linguaggio C++ 5 lezioni Lunedì, Giovedì ore 12.00-13.30 Alessandro Lonardo...

97
ntroduzione al linguaggio C++ lezioni unedì, Giovedì ore 12.00-13.30 lessandro Lonardo [email protected] avide Rossetti [email protected] agina WEB ttp://apegate.roma1.infn.it/~lonardo esti base: Bjarne Stroustrup, Il Linguaggio C++, ddison-Wesley. Brian W. Kernighan, Dennis M. Ritchie, l Linguaggio C, Jackson libri.

Transcript of Introduzione al linguaggio C++ 5 lezioni Lunedì, Giovedì ore 12.00-13.30 Alessandro Lonardo...

Page 1: Introduzione al linguaggio C++ 5 lezioni Lunedì, Giovedì ore 12.00-13.30 Alessandro Lonardo alessandro.lonardo@roma1.infn.it Davide Rossetti davide.rossetti@roma1.infn.it.

Introduzione al linguaggio C++

5 lezioni

Lunedì, Giovedì ore 12.00-13.30

Alessandro [email protected]

Davide Rossetti [email protected]

Pagina WEBhttp://apegate.roma1.infn.it/~lonardo

Testi base: -Bjarne Stroustrup, Il Linguaggio C++, Addison-Wesley.-Brian W. Kernighan, Dennis M. Ritchie,Il Linguaggio C, Jackson libri.

Page 2: Introduzione al linguaggio C++ 5 lezioni Lunedì, Giovedì ore 12.00-13.30 Alessandro Lonardo alessandro.lonardo@roma1.infn.it Davide Rossetti davide.rossetti@roma1.infn.it.

Programma del corso

Lezione 1a) Paradigmi di programmazioneb) Dichiarazionic) Tipid) Costanti

Lezione 2 a) Operatorib) Istruzioni c) Funzionid) Header Filee) Il Preprocessore f) Le librerie

Lezione 3 a) Classib) Interfacce ed implementazionic) Caratteristiche delle classid) Costruttori e distruttori

Lezione 4 a) Classi derivateb) Classi astrattec) Ereditarietà multiplad) Controllo dell’accessoe) Memoria dinamica

Page 3: Introduzione al linguaggio C++ 5 lezioni Lunedì, Giovedì ore 12.00-13.30 Alessandro Lonardo alessandro.lonardo@roma1.infn.it Davide Rossetti davide.rossetti@roma1.infn.it.

Lezione 5• Overload di Operatori• Template• La Standard Template Library

argomenti non trattati a lezione

Page 4: Introduzione al linguaggio C++ 5 lezioni Lunedì, Giovedì ore 12.00-13.30 Alessandro Lonardo alessandro.lonardo@roma1.infn.it Davide Rossetti davide.rossetti@roma1.infn.it.

Paradigmi di Programmazione

Programmazione ProceduraleSi definiscano le procedure desiderate;Si utilizzino gli algoritmi migliori.

-Programmatore concentrato sull’algoritmo

-Supporto fornito dai linguaggi: funzioni, procedure.(Fortran, Pascal, C...)

-Il programma viene suddiviso in funzioni, ogni funzionerealizza un algoritmo o una parte di esso.

Es.

double sqrt(double arg){//codice per il calcolo della radice quadrata}

void some_function(){ double root2 = sqrt(2.0); //...}

Page 5: Introduzione al linguaggio C++ 5 lezioni Lunedì, Giovedì ore 12.00-13.30 Alessandro Lonardo alessandro.lonardo@roma1.infn.it Davide Rossetti davide.rossetti@roma1.infn.it.

Programmazione Modulare

Modulo = Dati + Procedure;

Si decida quali sono i moduli necessari;Si suddivida il programma in modo che i dati siano nascosti neiModuli.

-Dati nascosti: nomi delle variabili, delle costanti e dei tipi sonoresi locali al modulo.

-Il linguaggio C consente l’impiego di questo paradigma attraversoIl concetto di unità di compilazione.

Es.File stack.h:

//dichiarazione della interfaccia per//il modulo stack di caratteri

void push(char);char pop();const int stack_size = 100;

Page 6: Introduzione al linguaggio C++ 5 lezioni Lunedì, Giovedì ore 12.00-13.30 Alessandro Lonardo alessandro.lonardo@roma1.infn.it Davide Rossetti davide.rossetti@roma1.infn.it.

File stack.cc (implementazione de modulo):

#include “stack.h” //usa l’interfaccia stack

//static significa: simbolo locale //a questo modulo (file)static char v[stack_size];

//lo stack viene inizializzato vuotostatic char* p = v;

void push(char c){ //implementazione}

char pop(){ //implementazione}

Page 7: Introduzione al linguaggio C++ 5 lezioni Lunedì, Giovedì ore 12.00-13.30 Alessandro Lonardo alessandro.lonardo@roma1.infn.it Davide Rossetti davide.rossetti@roma1.infn.it.

Uso del modulo stack di caratteri:

File bubu.cc:

#include “stack.h” //usa il modulo stack

void some_function(){ push(‘y’); char c = pop(); assert(c == ‘y’);}

-in questo file non si ha accesso alla struttura interna dello stack,è possibile utilizzare lo stack solo per mezzo delle funzioni esposte nell’interfaccia del modulo.

-Il linguaggio C++ estende il supporto del C alla programmazionemodulare attraverso l’uso delle classi.

Page 8: Introduzione al linguaggio C++ 5 lezioni Lunedì, Giovedì ore 12.00-13.30 Alessandro Lonardo alessandro.lonardo@roma1.infn.it Davide Rossetti davide.rossetti@roma1.infn.it.

Astrazione dei dati

Si decida quali tipi si desiderano;si fornisca un insieme completo di operazioni per ogni tipo.

-estende il concetto di modulo al caso in cui siano necessari piùoggetti di un certo tipo (come avrei fatto a dichiarare 2 stack?)

-I linguaggi che supportano la programmazione modulare permettono l’astrazione dei dati.

-Linguaggi come Ada, Java, C++... supportano il paradigmadella astrazione dei dati.

File complex.h://dichiarazione del tipo numero complessoclass Complex{ double re, im;public: Complex(double r, double i) {re = r; im = i;} Complex(double r) {re = r; im = 0;}

friend complex operator+(Complex, Complex); friend Complex operator-(Complex, Complex); friend Complex operator-(Complex);//unario friend Complex operator*(Complex, Complex); friend Complex operator/(Complex, Complex);};

Page 9: Introduzione al linguaggio C++ 5 lezioni Lunedì, Giovedì ore 12.00-13.30 Alessandro Lonardo alessandro.lonardo@roma1.infn.it Davide Rossetti davide.rossetti@roma1.infn.it.

File complex.cc://implementazione del tipo complex//...Complex operator+(Complex a1, Complex a2){ return Complex(a1.re+a2.re, a1.im+a2.im);}//...

File bubu.cc://uso del tipo complexvoid some_function(){ Complex a(2.0, 1.0), b(3.14), i(0.0, 1.0), c; c = a*i+b; //...}

-L’uso del tipo complex definito dall’utente è del tutto analogo a quello dei tipi predefiniti.

-Il tipo di dato astratto è una scatola nera. Il suo comportamentonon può essere cambiato, se non ridefinendo il tipo.Questa è una limitazione significativa.

Page 10: Introduzione al linguaggio C++ 5 lezioni Lunedì, Giovedì ore 12.00-13.30 Alessandro Lonardo alessandro.lonardo@roma1.infn.it Davide Rossetti davide.rossetti@roma1.infn.it.

Esempio: un sistema grafico che gestisce cerchi, triangoli e quadrati.

-Esistono i seguenti tipi astratti:class Point {//...};class Color {//...};enum Kind {circle, triangle, square};//rappresentazione di una formaclass Shape{ Point center; Color col; Kind k;public: point where() {return center;} void move(point to) {center = to; draw(); } void draw(); void rotate(int);};

-k è un “campo tipo” utile alle funzioni per determinare il tipo di formasu cui si lavora:

void Shape::draw() { switch(k) { case circle:

//disegna un cerchio case triangle:

//disegna un triangolo case square:

//disegna un quadrato }}

Page 11: Introduzione al linguaggio C++ 5 lezioni Lunedì, Giovedì ore 12.00-13.30 Alessandro Lonardo alessandro.lonardo@roma1.infn.it Davide Rossetti davide.rossetti@roma1.infn.it.

-Problemi:

1. draw() (come le altre operazioni) deve conoscere tuttti i tipi di forme su cui si lavora. Se si introduce una nuova forma ilcodice di draw() dovrà essere modificato.

2. Non è possibile aggiungere nel sistema la gestione di unanuova forma se non si ha accesso al codice sorgente di ognioperazione.

3. Ogni modifica espone il sistema alla introduzione di bug su codice già sviluppato.

-La sorgente di tutti questi problemi è la mancata espressione della distinzione tra le proprietà generali di una forma(ha un colore, ha una posizione, si può disegnare...) e le proprietà di una forma particolare (il cerchio ha un raggio, si disegna come uncerchio (!), ...).

-L’espressione di questa distinzione in modo utile per la scrittura del codice rappresenta la

Programmazione Orientata agli Oggetti

-Il supporto che il linguaggio C++ offre a questo paradigma è il meccanismo della ereditarietà.

Page 12: Introduzione al linguaggio C++ 5 lezioni Lunedì, Giovedì ore 12.00-13.30 Alessandro Lonardo alessandro.lonardo@roma1.infn.it Davide Rossetti davide.rossetti@roma1.infn.it.

-Il concetto di forma più generale:

class Shape{ Point center; Color col; //è sparito il fastidioso Kindpublic: point where() {return center;} void move(point to) {center = to; draw(); } virtual void draw(); //ora è virtual virtual void rotate(int); //ora è virtual};

-“virtual”: può essere ridefinito in una classe derivata

-Una forma particolare:

class Circle : public Shape{ int radius;public: void draw() {//disegna un cerchio!}; void rotate(int) {}//facile implementazione};

-La classe Circle è derivata (sottoclasse) dalla classe Shape.-La classe Shape è di base (superclasse) per la classe Circle.

Page 13: Introduzione al linguaggio C++ 5 lezioni Lunedì, Giovedì ore 12.00-13.30 Alessandro Lonardo alessandro.lonardo@roma1.infn.it Davide Rossetti davide.rossetti@roma1.infn.it.

Esempio di uso: funzione che prende un vettore di size forme e le ruota di angle gradi.

void rotate_all(Shape v[], int size, int angle){ int i = 0; while (i<size) { v[i].rotate(angle); i = i+1; }}

-l’elemento v[i]è in principio una forma qualsiasi, l’operazione di rotazione sarà quella che gli compete.

-Nella fase di progettazione del software è necessario individuare la massima quantità di elementi in comune tra i tipi del sistema e rappresentare queste similitudini utilizzando classi di base comuni.

Paradigma di programmazione orientata agli oggettiSi determini quali classi si desiderano;Si fornisca un insieme completo delle operazioni di ogni classe;Si espliciti ciò che hanno in comune per mezzo della ereditarietà

Page 14: Introduzione al linguaggio C++ 5 lezioni Lunedì, Giovedì ore 12.00-13.30 Alessandro Lonardo alessandro.lonardo@roma1.infn.it Davide Rossetti davide.rossetti@roma1.infn.it.

Dichiarazioni

-Identificatore C++: sequenza di lettere e cifre, il primo carattere deve essere una lettera (o “underscore”, ‘_’). Non si possono usare keyword. Case sensitive.

Buoni identificatori:Hello hello _bubu_ ApeMaiaun_identificatore_molto_lungo var1 var2

Non sono accettati:1var $pippo for lunghezza.massima

-Dichiarazione di un identificatore:Prima dell’uso di qualsiasi identificatore bisogna specificare ilSuo tipo:

Char c;int count = 1;char* name = “ciccio”;Const double pi=3.1415926535897932385float minus(float arg) { return -arg; }

-Queste sono anche definizioni di identificatori: definiscono l’entità alla quale il nome si riferisce.Per le variabili è la quantità di memoria allocata, per le funzionila loro implementazione, per le costanti il loro valore.

Page 15: Introduzione al linguaggio C++ 5 lezioni Lunedì, Giovedì ore 12.00-13.30 Alessandro Lonardo alessandro.lonardo@roma1.infn.it Davide Rossetti davide.rossetti@roma1.infn.it.

-le seguenti sono solo dichiarazioni:

extern float sqrt(float arg);extern int err_num;struct user;

-Una dichiarazione ha effetto in generale in un sottoinsieme delprogramma (visibilità).

int x; // x globale, visibile in tutto il pr.

void f(){ int x; //x locale, nasconde x globale x = 1; { int x; //locale, nasconde la prec. Locale x = 2; } x = 3;}

int* p = &x;

Page 16: Introduzione al linguaggio C++ 5 lezioni Lunedì, Giovedì ore 12.00-13.30 Alessandro Lonardo alessandro.lonardo@roma1.infn.it Davide Rossetti davide.rossetti@roma1.infn.it.

Oggetto : zona di memoria

lvalue: espressione che fa riferimento ad un oggetto

-Un oggetto viene creato all’atto della sua definizione e distrutto quando non è più visibile (anche i locali definiti static)

int a = 1;

void f(){ int b = 1; //inizializzato ad ogni chiamata static int c = a; //ini. una sola volta cout << “ a = “ << a++

<< “ b = “ << b++<< “ c = “ << c++ << endl;

}

int main(){ while ( a < 4 ) f();}

Output:

a = 1 b = 1 c = 1a = 2 b = 1 c = 2a = 3 b = 1 c = 3

Page 17: Introduzione al linguaggio C++ 5 lezioni Lunedì, Giovedì ore 12.00-13.30 Alessandro Lonardo alessandro.lonardo@roma1.infn.it Davide Rossetti davide.rossetti@roma1.infn.it.

Tipi

il tipo specifica le operazioni che si possono compire sul datoe la loro semantica

Tipi fondamentali:void

Tipi interi:boolcharshort intintlong int

Tipi floating point (reali):floatdoublelong double

Tipi interi senza segno, valori logici, vettori di bit:unsigned charunsigned short intunsigned intunsigned long int

Per esplicitare i tipi interi con segno:signed charsigned short intsigned intsigned long int

-se il tipo è omesso si assume int

Page 18: Introduzione al linguaggio C++ 5 lezioni Lunedì, Giovedì ore 12.00-13.30 Alessandro Lonardo alessandro.lonardo@roma1.infn.it Davide Rossetti davide.rossetti@roma1.infn.it.

-tipi interi e floating point diversi, diversa occupazione di memoria, velocità di esecuzione...

-Il linguaggio definisce solo queste restrizioni:

1==sizeof(char)<=sizeof(short)<=sizeof(int)<=sizeof(long)

sizeof(float)<=sizeof(double)<=sizeof(long double)

sizeof(I)==sizeof(signed I) == sizeof(unsigned I)

Ad esempio, architettura IA32:

bool 8 bitchar 8 bitshort 16 bitint 32 bitlong int 32 bit

float 32 bitdouble 64 bitlong double 80 bit

Page 19: Introduzione al linguaggio C++ 5 lezioni Lunedì, Giovedì ore 12.00-13.30 Alessandro Lonardo alessandro.lonardo@roma1.infn.it Davide Rossetti davide.rossetti@roma1.infn.it.

Conversione tra i tipi

-implicita: in generale si possono mescolare liberamente variabilidi tipo diverso in una espressione.(non è un bello stile...)

int i = 2;float f, g = 2.0;f = i * g - 4;

-esplicita: float r = (float) 2; //castfloat r = float(2);

-promozioni

Tipi derivati

-definiti a partire da quelli base o user-defined per mezzo degli operatori di dichiarazione:

* puntatore& reference[] array

Esempio:

int* pi; //tipo = puntatore ad intdouble& d; //tipo = reference a double float v[10]; //tipo = vettore di 10 float

Page 20: Introduzione al linguaggio C++ 5 lezioni Lunedì, Giovedì ore 12.00-13.30 Alessandro Lonardo alessandro.lonardo@roma1.infn.it Davide Rossetti davide.rossetti@roma1.infn.it.

-Un altro modo di introdurre un tipo derivato è la definizione di una struttura:

struct Point

{

int x;

int y;

};

Point a,b,c;

Page 21: Introduzione al linguaggio C++ 5 lezioni Lunedì, Giovedì ore 12.00-13.30 Alessandro Lonardo alessandro.lonardo@roma1.infn.it Davide Rossetti davide.rossetti@roma1.infn.it.

Puntatori

puntatore: variabile che contiene l'indirizzo di un'altra variabile-In C++ i puntatori hanno un tipo associato (eccezione void *).

'y'char c = 'y';

char* p;

p = &c;

char c2 = *p;

c

'y' null

c p

'y'

c p

&c

'y' &c

c p

'y'

c2

&c: indirizzo di c.

*p: dereferenziazione di p, accesso all'oggetto puntato.

-avrei potuto scrivere: char *p = &'y'?

Page 22: Introduzione al linguaggio C++ 5 lezioni Lunedì, Giovedì ore 12.00-13.30 Alessandro Lonardo alessandro.lonardo@roma1.infn.it Davide Rossetti davide.rossetti@roma1.infn.it.

no! ottengo: non-lvalue in unary '&'.

Naturalmente posso dichiarare un puntatore a puntatore:

char** pp = &p; 'y' &c c p

'y'

c2

&p

pp

**pp = 'z'; 'z' &c 'y'

&p

pp

c p c2

cout << c << '\t' << c2 << endl;

in output:

z y

Page 23: Introduzione al linguaggio C++ 5 lezioni Lunedì, Giovedì ore 12.00-13.30 Alessandro Lonardo alessandro.lonardo@roma1.infn.it Davide Rossetti davide.rossetti@roma1.infn.it.

-se p è un puntatore di tipo T* allora *p può comparire ovunque ci si aspetti un oggetto di tipo T:

int i = 4;int* pi = &i;int* pi2;*pi = *pi + 1; //i=5pi2 = pi;*pi2 = i * 2; //i=10

Quanto vale i?

-void*: è il tipo che corrisponde ai puntatori generici, qualsiasipuntatore può essere convertito a void* e poi riconvertito nel suo tipo originale senza perdita di informazione.Questo tipo è utilissimo come parametro di funzioni.

Page 24: Introduzione al linguaggio C++ 5 lezioni Lunedì, Giovedì ore 12.00-13.30 Alessandro Lonardo alessandro.lonardo@roma1.infn.it Davide Rossetti davide.rossetti@roma1.infn.it.

-In realtà esistono anche puntatori a funzione

int (*funp) (int, int);

è la dichiarazione di un puntatore di nome funp ad una funzione che accetta due parametri di tipo int e restituendo un tipo int come risultato.La dereferenziazione di funp restituisce una funzione. Esempio:

//restituisce il massimo tra arg1 e arg2int max(int arg1, int arg2) {//...}//restituisce il minimo tra arg1 e arg2int min(int arg1, arg2) {//...}int (*funp) (int, int);int i = 1, j = 2, k, l;

funp = &max; k = (*funp)(i, j);funp = &min;l = (*funp)(i, j);

Quanto valgono k ed l?

Page 25: Introduzione al linguaggio C++ 5 lezioni Lunedì, Giovedì ore 12.00-13.30 Alessandro Lonardo alessandro.lonardo@roma1.infn.it Davide Rossetti davide.rossetti@roma1.infn.it.

array

tipo T, T[size] è un vettore di size elementi di tipo T.

-L'indice è compreso tra 0 e size-1.

-size deve essere una costante intera; alcune implementazionidel compilatore (ad es. GNU) permettono l'uso di variabili o espressioni intere.

float v[3]; //v[0], v[1], v[2]int m[2][3];//2 vettori di 3 interichar* vpc[10];//vettore di 10 punt. a char

-Inizializzazione://v[] ha 6 elementiint v[] = {137, -12, 53, 12943, 21, -20};

float vf[] = {12.2, 0.1, -22.1};

double id[3][3] ={{1.0, 0.0, 0.0},{0.0, 1.0, 0.0},{0.0, 0.0, 1.0}};

char vc[] = {'c', 'i', 'a', 'o', '\0'};

Page 26: Introduzione al linguaggio C++ 5 lezioni Lunedì, Giovedì ore 12.00-13.30 Alessandro Lonardo alessandro.lonardo@roma1.infn.it Davide Rossetti davide.rossetti@roma1.infn.it.

-solo per i vettori di char si può utilizzare una notazione più comoda:

char vocali[] = "aeiou";//in questo caso il carattere di fine stringa//viene aggiunto automaticamente

-boundary checking: no!Il compilatore non controlla la correttezza degli indici degli elementi diarray. Si può facilmente ottenere un errore.

Puntatori ed array-Il nome di un array può anche essere usato come puntatore al suo primoelemento:

int v[10];int* pi = v;

*pi = 0;//equivale a v[0] = 0pi++; //ora pi punta a v[1]*pi = 1;//v[1] = 1pi--; //ora pi punta a v[0]pi = pi +5 ; //ora pi punta a v[5]int offset = pi - v; //numero di el. tra i 2 p.

aritmetica dei puntatori+, -, ++, --. Da usare con grande cautela, è facile puntare ad aree di memoria sbagliateuscita dal programma con errore, il famigerato segmentation fault

Page 27: Introduzione al linguaggio C++ 5 lezioni Lunedì, Giovedì ore 12.00-13.30 Alessandro Lonardo alessandro.lonardo@roma1.infn.it Davide Rossetti davide.rossetti@roma1.infn.it.

Strutture

Meccanismo per introdurre tipi di dato costituiti da un insieme dielementi di tipi (anche) diversi.

struct Particle {

double p[3];

double v[3];

int charge;

};

-si possono dichiarare variabili di questo nuovo tipo:

Particle p1, p2, p3;

-si può accedere ai campi del tipo usando l'operatore .

p1.p[0] = p1.p[1] = p1.p[2] = 0.0;p1.v[0] = p1.v[1] = p1.v[2] = 0.0;p1.charge = -1;//poi vedremo che risulta più comodo//utilizzare il costruttore//... p2 = p1;//...

Page 28: Introduzione al linguaggio C++ 5 lezioni Lunedì, Giovedì ore 12.00-13.30 Alessandro Lonardo alessandro.lonardo@roma1.infn.it Davide Rossetti davide.rossetti@roma1.infn.it.

-il nome del tipo risulta utilizzabile anche nella definizione del tipostesso:

struct Link{ Link* prev; Link* succ;};

-ma ciò non significa che si possono dichiarare oggetti del nuovo tipodurante la sua dichiarazione!

struct NewType{ NewType x; //ERRORE IN COMPILAZIONE //...};

-Come si gestiscono i riferimenti incrociati durante le dichiarazioni?

Meccanismo della forward declaration.

Page 29: Introduzione al linguaggio C++ 5 lezioni Lunedì, Giovedì ore 12.00-13.30 Alessandro Lonardo alessandro.lonardo@roma1.infn.it Davide Rossetti davide.rossetti@roma1.infn.it.

Esempio:

struct List; //dichiarazione non definizione

struct Link{ Link* prev; Link* succ; List* member_of;};

struct List{ Link* head;};

-In generale il nome della struct può essere utilizzato prima della suadefinizione quando non è necessario conoscere la sua dimensione.

struct Astruct;

void f(Astruct); //no problem

Astruct a; //Errore!f(a); //Errore!

Page 30: Introduzione al linguaggio C++ 5 lezioni Lunedì, Giovedì ore 12.00-13.30 Alessandro Lonardo alessandro.lonardo@roma1.infn.it Davide Rossetti davide.rossetti@roma1.infn.it.

typedef

-introduce un nuovo nome per un tipo

-comodo per costruire convenzioni proprie:

typedef double Mass;typedef double Distance;

Mass m1, m2, m3;Distance d1, d2, d3;

-esempi abbastanza comuni:

typedef unsigned char uchar;typedef unsigned short ushort;typedef unsigned int uint;

-è utile per abbreviare tipi complicati (come i puntatori a funzione):

typedef void (*calc_func)(float);calc_func func_table[10];

è certamente più espressivo di:

void (* func_table[10])(float);

Page 31: Introduzione al linguaggio C++ 5 lezioni Lunedì, Giovedì ore 12.00-13.30 Alessandro Lonardo alessandro.lonardo@roma1.infn.it Davide Rossetti davide.rossetti@roma1.infn.it.

reference

nome alternativo di un oggetto

-tipo T, T& significa riferimento a T.

int i = 1;int& r = i; //r ed i si rif. allo stesso intint x = r; // x = 1r = 2; // i = 2

-Una reference deve essere sempre inizializzato (a cosa riferirebbe?) -Inizializzazione reference != assegnamento di variabile

-Gli operatori applicati ad una reference non agiscono su di essa, masull'oggetto a cui si riferisce:

int ii = 0;int& rr = ii;rr++; //è ii che viene incrementato, non rr

-una reference non può essere modificata dopo l'inizializzazione.

-Come vedremo sono utili come parametri di funzioni e nella definizionedegli operatori definiti dall'utente.

Page 32: Introduzione al linguaggio C++ 5 lezioni Lunedì, Giovedì ore 12.00-13.30 Alessandro Lonardo alessandro.lonardo@roma1.infn.it Davide Rossetti davide.rossetti@roma1.infn.it.

costanti senza nome

-costanti intere:

decimali 0 137 12 3 1ottali 0 064 0237esadecimali 0x0 0x3 0x7fff 0xfefe

-suffissi U, L, LL:

void f(int);void f(unsigned int);void f(long int);void f(long long int);

f(3);f(3U);f(3L);f(3LL);

-costanti floating point:

0.0 1.37 2. 1.3e10 1.6e-15

-costanti carattere (ASCII, EBCDIC, UNICODE...)'a' '2' '\n' '\t'

si può, ma è meglio evitare (portabilità del codice):

'\137' '\x05f' 95 codice ASCII di '_'

Page 33: Introduzione al linguaggio C++ 5 lezioni Lunedì, Giovedì ore 12.00-13.30 Alessandro Lonardo alessandro.lonardo@roma1.infn.it Davide Rossetti davide.rossetti@roma1.infn.it.

costanti con nome

la keyword const premessa alla dichiarazione di un oggetto lo rendeuna costante invece di una variabile (deve essere inizializzato):

const int bu = 20;bu++; //ERRORE

const char* pippo = "abcde";-Chi è costante il puntatore o l'oggetto puntato?

pippo[2] = 'z'; //ERROREpippo = "ciccio";

ovvero ho dichiarato un puntatore a costante.

-Per rendere costante il puntatore si usa l'operatore *const

char *const bubu = "yogi";bubu[3] = 'a';bubu = "napo"; //ERROREovvero ho dichiarato un puntatore costante.

-infine:const char *const cp = "fred";

-notare che non si può:const int x = 10;int* pi = &x; //ERRORE, potrei modificare xconst int* pic = &x; //no problem

-vantaggi per il compilatore usando const (e ovviamente per l'utente).

Page 34: Introduzione al linguaggio C++ 5 lezioni Lunedì, Giovedì ore 12.00-13.30 Alessandro Lonardo alessandro.lonardo@roma1.infn.it Davide Rossetti davide.rossetti@roma1.infn.it.

-un nome simbolico per ogni costante:

enum { PICCOLO, MEDIO, GRANDE };

equivale a:

const int PICCOLO = 0;

const int MEDIO = 1;

const int GRANDE = 2;

-è possibile assegnare un nome, facendo diventare l'enum un nuovo

tipo:

enum Verdure

{

RAPE,

BROCCOLI,

CIPOLLE

};

//...

Verdure cose_da_comprare;

cose_da_comprare = RAPE;

int j = BROCCOLI;

Verdure da_preparare = 2; //ERRORE!!

Verdure da_preparare = Verdure(2); //OK

enum

Page 35: Introduzione al linguaggio C++ 5 lezioni Lunedì, Giovedì ore 12.00-13.30 Alessandro Lonardo alessandro.lonardo@roma1.infn.it Davide Rossetti davide.rossetti@roma1.infn.it.

-in realtà gli enumeratori si possono inizializzare a piacere:

enum Colors

{

red = 2,

green,

blue = green + 1,

grey = blue * 2

};

//...

cout << grey << ' ' << blue << ' '

<< green << ' ' << red << endl;;

Cosa ottengo in uscita?

enum <---> switch

Page 36: Introduzione al linguaggio C++ 5 lezioni Lunedì, Giovedì ore 12.00-13.30 Alessandro Lonardo alessandro.lonardo@roma1.infn.it Davide Rossetti davide.rossetti@roma1.infn.it.

union

-definisce piu` modi di vedere lo stesso oggetto:

// nell’ipotesi sizeof(int)==4

union MultipleAccess

{

int word_value;

unsigned short halfword_values[2];

unsigned char byte_values[4];

};

-come si usa ?

MultipleAccess value;

value.word_value = 0xA3458543;

//cosi` accedo ai bytes:

unsigned char first_byte = value.byte_values[0];

//cosi` alle parole di 16 bit (half word):

unsigned short second_halfword =

value.halfword_values[1];

cout << hex << value.word_value << ' '

<< (int) first_byte << ' '

<< second_halfword << endl;

-cosa ottengo in uscita?

Page 37: Introduzione al linguaggio C++ 5 lezioni Lunedì, Giovedì ore 12.00-13.30 Alessandro Lonardo alessandro.lonardo@roma1.infn.it Davide Rossetti davide.rossetti@roma1.infn.it.

word = a3458543 byte[0] = 43 halfword[1] = a345

-E' utilissimo quando si abbia necessita di risparmiare memoria(lo stesso spazio occupa oggetti diversi in momenti diversi):

enum EntryType { STRING, INT};union EntryValue{ char* string_val; int int_val;};

struct Entry{ char* name; EntryType type; EntryValue value;};

//... Entry a[10]; a[0].name = "Pippo"; a[0].type = STRING; a[0].value.string_val = "Amico di Topolino";

a[1].name = "Targa di Paperino"; a[1].type = INT; a[1].value.int_val = 313;

Page 38: Introduzione al linguaggio C++ 5 lezioni Lunedì, Giovedì ore 12.00-13.30 Alessandro Lonardo alessandro.lonardo@roma1.infn.it Davide Rossetti davide.rossetti@roma1.infn.it.

campi di bit

-modo per inserire oggetti di dimensioni ridotte in una sola word(economizzando lo spazio occupato).

struct { unsigned int sign : 1; unsigned int exponent: 8; unsigned int fraction0: 7; unsigned int fraction1: 16; } number;

-i campi si comportano come degli interi (di dimensione ridotta)

-Tutti i dettagli (come avviene l'allocazione dei campi in memoria...)dipendono dalla macchina.

-Tipo di dato con cui è facile scrivere codice non portabile

Page 39: Introduzione al linguaggio C++ 5 lezioni Lunedì, Giovedì ore 12.00-13.30 Alessandro Lonardo alessandro.lonardo@roma1.infn.it Davide Rossetti davide.rossetti@roma1.infn.it.

-aritmetici (tipi interi e floating point):

+ - * /

% resto della div. int (modulo)

++ -- pre e post incremento/decremento

- + unari

-esempio:

int i, j, inc_i, j_inc;

i = j = 3;

inc_i = ++i;

j_inc = j++;

cout << i << '\t' << j << '\t'

<< inc_i << '\t' << j_inc << endl;

ottengo:

4 4 4 3

operatori

Page 40: Introduzione al linguaggio C++ 5 lezioni Lunedì, Giovedì ore 12.00-13.30 Alessandro Lonardo alessandro.lonardo@roma1.infn.it Davide Rossetti davide.rossetti@roma1.infn.it.

-relazionali:

> >= < <=

== !=

-logici:

&& AND

|| OR

! NOT

le espressioni formate con questi operatori vengono valutate da sin.

a destra, bloccandosi non appena si determina il risultato.

Attenzione!

int ciao()

{

cout << "Ciao" << endl;

return 1;

}

//...

int i = 10;

unsigned booleano = (i == 10) || (ciao() == 1);

Verremo salutati?

Page 41: Introduzione al linguaggio C++ 5 lezioni Lunedì, Giovedì ore 12.00-13.30 Alessandro Lonardo alessandro.lonardo@roma1.infn.it Davide Rossetti davide.rossetti@roma1.infn.it.

-bit a bit (tipi interi), utili per lavorare con vettori di bit:

& AND

| OR

^ XOR

<< shift a sinistra

>> shift a destra (logico/aritmetico)

~ complemento ad uno

-mascherare (azzerare) insiemi di bit: AND

n = n & 0xF0 //11110000

-accendere insiemi di bit: OR

n = n | 0x1; //dispari

-moltiplicare per potenze di 2 (x = y * 2 z)

x = y << z;

-dividere per potenze di 2 (x = y / 2 z)

x = y >> z;

- mascherare il bit meno significativo:

n = n & (~0x1);

Page 42: Introduzione al linguaggio C++ 5 lezioni Lunedì, Giovedì ore 12.00-13.30 Alessandro Lonardo alessandro.lonardo@roma1.infn.it Davide Rossetti davide.rossetti@roma1.infn.it.

-assegnamento (semplice e composto):

= assegnamento

*= /= %= += -=

<<= >>= &= |= ^=

es: a *= 2; ---> a = a * 2;

-vari:

. selezione elemento object.member

-> selezione elemento pointer->member

es:

struct Color

{

int r,g,b;

};

//...

Color c;

Color* pc = &c;

//...

c.r = pc->r;

Page 43: Introduzione al linguaggio C++ 5 lezioni Lunedì, Giovedì ore 12.00-13.30 Alessandro Lonardo alessandro.lonardo@roma1.infn.it Davide Rossetti davide.rossetti@roma1.infn.it.

[] indicizzazione pointer[expr]

() chiamata di funzione expr(expr_list)

() costruzione valore type(expr_list)

& indirizzo di &lvalue

* dereferenziazione *expr

new crea un oggetto new type

delete distrugge un oggetto delete pointer

sizeof dimensioni del tipo sizeof type

sizeof dimensioni oggetto sizeof expr

:: scope resolution class_name::member

?: espressione condiz. expr?expr:expr

, virgola expr, expr

Page 44: Introduzione al linguaggio C++ 5 lezioni Lunedì, Giovedì ore 12.00-13.30 Alessandro Lonardo alessandro.lonardo@roma1.infn.it Davide Rossetti davide.rossetti@roma1.infn.it.

associatività

-unari e assegnamento associativi a destra:

a = b = c ---> a = ( b = c )

*p++ ---> *(p++) //non (*p)++

-tutti gli altri sono associativi a sinistra

precedenza degli operatori: manuale di riferimento!

-esiste la forma funzionale di quasi tutti gli operatori visti:

double n1 = 1.33;

double n2 = .3E-2;

double result;

result = operator+(n1,n2);

-e` come se il compilatore avesse predefinite e utilizzato le

funzioni speciali:

double operator +(const double &d1,

const double &d2);

idem per:

int operator <(const int &n1, const int &n2);

int operator ~(const int &n1);

int operator >>=(const int &n1,

const int &n2);

-nessuno usa questa forma, di solito, ma servono per l’overloading

nei tipi definiti dall'utente

Page 45: Introduzione al linguaggio C++ 5 lezioni Lunedì, Giovedì ore 12.00-13.30 Alessandro Lonardo alessandro.lonardo@roma1.infn.it Davide Rossetti davide.rossetti@roma1.infn.it.

if-else

permette di esprimere una decisione

if(espressione)

istruzione_1

else

istruzione_2

-per istruzione si intende anche un blocco di istruzioni (sequenza di

dichiarazioni ed istruzioni tra parentesi graffe), che a sua volta può

contenere altri blocchi...

es.

if( a > b )

max = a;

else

max = b;

costrutti

Page 46: Introduzione al linguaggio C++ 5 lezioni Lunedì, Giovedì ore 12.00-13.30 Alessandro Lonardo alessandro.lonardo@roma1.infn.it Davide Rossetti davide.rossetti@roma1.infn.it.

switch-case

permette di operare delle scelte multiplecontrollando se una espressione assume uncerto valore in un insieme di costanti intere

switch (espressione){ case const_expr1 : istruzioni case const_expr2 : istruzioni ... default : istruzioni}

-Risulta conveniente (e migliora la leggibilità del codice) usaredegli enum come valori possibili per i case.

Page 47: Introduzione al linguaggio C++ 5 lezioni Lunedì, Giovedì ore 12.00-13.30 Alessandro Lonardo alessandro.lonardo@roma1.infn.it Davide Rossetti davide.rossetti@roma1.infn.it.

es.

enum Animale {CANE, GATTO, TOPO};Animale bu;//...switch(bu) { case CANE:

cout << “BAU!" << endl;break;

case GATTO:cout << “MIAO!” << endl;break;

case TOPO:cout << “SQUIT!” << endl;break;

default:cout << “Un minollo?” << endl;break;

}

Page 48: Introduzione al linguaggio C++ 5 lezioni Lunedì, Giovedì ore 12.00-13.30 Alessandro Lonardo alessandro.lonardo@roma1.infn.it Davide Rossetti davide.rossetti@roma1.infn.it.

while

permette di eseguire iterativamente una istruzione (o blocco)

while (espressione)

istruzione

espressione viene valutata, se il suo valore

!= 0 allora viene eseguita istruzione ed

espressione viene valutata di nuovo.

Il ciclo si interrompe quando espressione

diventa falsa (uguale a 0).

-istruzione a seconda del valore di espressione

puo` anche non esser mai eseguita.

es.

while(i == 0 && j < 100)

{

//...

if (ww)

break; //esci dal while

if (kk)

continue;//riparti dalla iterazione succ.

v1[j] = v2[j] + v3[j++];//attenzione

}

Page 49: Introduzione al linguaggio C++ 5 lezioni Lunedì, Giovedì ore 12.00-13.30 Alessandro Lonardo alessandro.lonardo@roma1.infn.it Davide Rossetti davide.rossetti@roma1.infn.it.

do-while

controlla la condizione di uscita al termine

di ogni iterazione

do

istruzione

while (espressione);

-e` eseguito almeno una volta :

int k = 0;

...

do

{

k++;

} while(k < 100);

Page 50: Introduzione al linguaggio C++ 5 lezioni Lunedì, Giovedì ore 12.00-13.30 Alessandro Lonardo alessandro.lonardo@roma1.infn.it Davide Rossetti davide.rossetti@roma1.infn.it.

for

struttura iterativa alternativa allo while

for (espr1; espr2; espr3)

istruzione

equivale a:

espr1;

while (espr2)

{

istruzione

espr3;

}

-in molti casi è piu' comodo da usare

for( solo_la_prima_volta;

all_inizio_di_ogni_ciclo;

alla_fine_di_ogni_ciclo)

{

// in qualunque momento posso:

// uscire dal ciclo con break

// oppure andare direttamente

// alla iterazione succ. con continue

}

Page 51: Introduzione al linguaggio C++ 5 lezioni Lunedì, Giovedì ore 12.00-13.30 Alessandro Lonardo alessandro.lonardo@roma1.infn.it Davide Rossetti davide.rossetti@roma1.infn.it.

-esempio, trovare il numero di bit ad 1 della variabile x

unsigned int x, tmp;

unsigned char nbit;

//...

for(nbit = 0, tmp = x; tmp != 0; tmp >>= 1)

if( (tmp & 0x1) != 0)

nbit++;

//...

l'operatore virgola!

Page 52: Introduzione al linguaggio C++ 5 lezioni Lunedì, Giovedì ore 12.00-13.30 Alessandro Lonardo alessandro.lonardo@roma1.infn.it Davide Rossetti davide.rossetti@roma1.infn.it.

-esiste anche il goto!

goto identificatore;identificatore : istruzione

-è meglio evitarlo! Ma in alcuni casi può servire(codice generato automaticamente, applicazioni real-time...)

for (i = 0; i < n ; i++) for (j = 0; j < m; j++) if (a[i] == b[j]) goto trovato;//salta alla label trovato //non ha trovato elementi comuni //...trovato: //trovato un elemento in comune //...

Page 53: Introduzione al linguaggio C++ 5 lezioni Lunedì, Giovedì ore 12.00-13.30 Alessandro Lonardo alessandro.lonardo@roma1.infn.it Davide Rossetti davide.rossetti@roma1.infn.it.

funzioni

parte di un programma che svolge un determinato compito

-dichiarazione: si specificano il nome della funzione, il tipo ed il numero dei parametri in ingresso, il tipo del valore di ritorno

int lsh(const int& op1, const int& op2);

nella dichiarazione i nomi degli argomenti in ingresso sono utili peraggiungere informazione sulla semantica della funzione, ma vieneignorato dal compilatore:

extern char* strcpy(char* to, const char* from);

-definizione:

tipo-ritornato nome-funzione(dich. args){ dichiarazioni ed istruzione}

-rispetto alla dichiarazione ho aggiunto il corpo della funzione

extern int min(int op1, int op2);//dichiar.

int min(int op1, int op2) //definizione{ int min = op1 < op2? op1 : op2; return min;}

Page 54: Introduzione al linguaggio C++ 5 lezioni Lunedì, Giovedì ore 12.00-13.30 Alessandro Lonardo alessandro.lonardo@roma1.infn.it Davide Rossetti davide.rossetti@roma1.infn.it.

inline

-specificando che una funzione è inline si dice al compilatore diespandere il codice di una funzione ad ogni sua chiamata piuttostodi effettuare una chiamata vera e propria (efficienza/memoria).

...ora calma e sangue freddo...

inline int fatt(int i) { return i < 2 ? 1 : i*fatt(i-1); }

ricorsione: funzione che richiama se stessa

-quale è la sequenza di chiamate?

int res = fatt(5);

fatt(5) -> 5 * fatt(4) = 120fatt(4) -> 4 * fatt(3) = 24fatt(3) -> 3 * fatt(2) = 6fatt(2) -> 2 * fatt(1) = 2fatt(1) -> 1

la mente si confonde...allora poi si cita sempre la famosa frase:

l'iterazione è umana,la ricorsione è divina!

Page 55: Introduzione al linguaggio C++ 5 lezioni Lunedì, Giovedì ore 12.00-13.30 Alessandro Lonardo alessandro.lonardo@roma1.infn.it Davide Rossetti davide.rossetti@roma1.infn.it.

parametri

-formali , attuali:

double sqrt(double d) { //... }//... double x, res;//...res = sqrt(x);

x:attualed:formale

-type checking, conversioni

-passaggio di parametri per valore e per riferimento

void f(int val, int& ref){ val++; //inc una copia locale del par. val ref++; //inc il par. ref}

-i maestri sconsigliano l'uso esteso del passaggio by ref (io no)

Comunque il passaggio per riferimento è essenziale per ottenereun codice efficiente quando si definiscono funzioni che accettanoparametri in ingresso di grandi dimesioni (si evita la copia del par.)

void f(const TipoGrande& arg) { //... }

Page 56: Introduzione al linguaggio C++ 5 lezioni Lunedì, Giovedì ore 12.00-13.30 Alessandro Lonardo alessandro.lonardo@roma1.infn.it Davide Rossetti davide.rossetti@roma1.infn.it.

-parametri array:

un argomento T[] viene convertito in un T* nel passaggio, quindil'array non può essere passato per valore.

float dot(float v1[], float v2[], int dim){ float res = 0.0; for(int i = 0; i < dim; i++) res += v1[i] * v2[i];

//equivalente a: // for(int i = 0; i < dim; i++) // res += *v1++ * *v2++;

return res;}

-per gli array multidimensionali è necessario specificare tutte le dimensioni tranne la prima:

//ERROREfloat* mul(float m1[][], float m2[][], int d1, int d2, int d3, int d4 );//OKfloat* f(float m1[][100], float m2[][200], int d1, int d2);

Page 57: Introduzione al linguaggio C++ 5 lezioni Lunedì, Giovedì ore 12.00-13.30 Alessandro Lonardo alessandro.lonardo@roma1.infn.it Davide Rossetti davide.rossetti@roma1.infn.it.

overload

stesso nome per operazioni diverse su tipi diversi

void print(int);void print(char *);

attenzione: non si può ridefinire il tipo ritornato!

-parametri di default:

void print(int val, int base = 10)//...print(16);print(16, 10);print(16, 2);

16 16 10000

-i parametri opzionali vanno messi per ultimi!

-numero non specificato di parametri:

int printf(const char* ...);

è possibile farlo, ma l'utilità è veramente rara --> Manuale!

Page 58: Introduzione al linguaggio C++ 5 lezioni Lunedì, Giovedì ore 12.00-13.30 Alessandro Lonardo alessandro.lonardo@roma1.infn.it Davide Rossetti davide.rossetti@roma1.infn.it.

Preprocessore

realizza la prima fase, separata dalle altre, della compilazione trasformando il codice sorgente

-principalmente:

#include "nomefile" sostituisce la linea con il contenuto di nomefile (cerca nomefile nellastessa dir, se non è specificato un path completo)

#include <nomefile>come sopra, però nomefile viene cercato nelle directory standard di inclusione: /usr/include, /usr/local/include

-tipicamente i file che vengono inclusi sono header file (.h)questi contengono tipicamente:

•definizione di tipi, struct Color {int r,g,b;}•template (vedremo)•dichiarazione di funzioni, variabili, costanti •dichiarazioe di nomi, struct Token• #include, #define•...

Page 59: Introduzione al linguaggio C++ 5 lezioni Lunedì, Giovedì ore 12.00-13.30 Alessandro Lonardo alessandro.lonardo@roma1.infn.it Davide Rossetti davide.rossetti@roma1.infn.it.

#define nome testo da sostituiresostituisce ad un identificatore una stringa arbitraria.

#define MAX 100 //...int v[MAX];//...

diventa://...int v[100];//...

Si usa per definire macro:

#define min(a,b) a<b?a:b//...int c = min(1, x);//...

diventa://...int c = 1<x?1:x;//...

-evitare l'uso eccessivo delle macro!

Il C++ offre costrutti alternativi: const, inline, template

Page 60: Introduzione al linguaggio C++ 5 lezioni Lunedì, Giovedì ore 12.00-13.30 Alessandro Lonardo alessandro.lonardo@roma1.infn.it Davide Rossetti davide.rossetti@roma1.infn.it.

inclusione condizionale

permette di inserire selettivamente parti di codice

-codice sorgente che compila correttamente su diverse architetture:

#ifdef UNIX #include "unix.h"#else #include "msdos.h"#endif

-definire in modo selettivo le macro

#ifdef VERBOSE #define message(m) cerr << m;#else #define message(m)#endif

-proteggere da inclusioni multiple:

#ifndef _HEADER_H_#define _HEADER_H-//contenuto del file header.h#endif

Page 61: Introduzione al linguaggio C++ 5 lezioni Lunedì, Giovedì ore 12.00-13.30 Alessandro Lonardo alessandro.lonardo@roma1.infn.it Davide Rossetti davide.rossetti@roma1.infn.it.

varie

#warning “this header is version 1.2”

#error “I compile only from v1.2 on”

#pragma optimization(on)

# : string-ification

enum Colors { red, green, blue, yellow };

#define FILL_LIST(NAME) { NAME, #NAME }

struct { Colors c; const char *name;} color_list[] = { FILL_LIST(red), FILL_LIST(green), //... { 0, NULL } };

-nomi predefiniti:

__LINE__ costante int, numero corrente del codice sorgente__FILE__ stringa, nome del file sotto compilazione__DATE__ stringa, data della compilazione __TIME__ stringa, ora della compilazione

Page 62: Introduzione al linguaggio C++ 5 lezioni Lunedì, Giovedì ore 12.00-13.30 Alessandro Lonardo alessandro.lonardo@roma1.infn.it Davide Rossetti davide.rossetti@roma1.infn.it.

Preprocesorcpp

.cc, .heditor

C++Compiler

Assembleras

Linkerln

.ii

.s

.o

lib?.aexe

esecuzione

codice espanso

.hheader filedi sistema

.so

librerie dinamiche

assemby

.oaltri fileoggetto

catena di compilazione

Page 63: Introduzione al linguaggio C++ 5 lezioni Lunedì, Giovedì ore 12.00-13.30 Alessandro Lonardo alessandro.lonardo@roma1.infn.it Davide Rossetti davide.rossetti@roma1.infn.it.

hello.cc (C++)

#include <iostream.h>

void main(){ cout << "Ciao!!!" << endl;}

Page 64: Introduzione al linguaggio C++ 5 lezioni Lunedì, Giovedì ore 12.00-13.30 Alessandro Lonardo alessandro.lonardo@roma1.infn.it Davide Rossetti davide.rossetti@roma1.infn.it.

hello.ii (Output del Preprocessore)

//qua sopra ci sono mooolte righe class _IO_ostream_withassign : public ostream {public: _IO_ostream_withassign& operator=(ostream&); _IO_ostream_withassign& operator=(_IO_ostream_withassign& r { return operator= (static_cast<ostream&> (rhs)); }};

extern _IO_istream_withassign cin;extern _IO_ostream_withassign cout, cerr;extern _IO_ostream_withassign clog;

extern istream& lock(istream& ins);extern istream& unlock(istream& ins);extern ostream& lock(ostream& outs);extern ostream& unlock(ostream& outs);

struct Iostream_init { } ;

inline ios& dec(ios& i){ i.setf(ios::dec, ios::dec|ios::hex|ios::oct); return i; }inline ios& hex(ios& i){ i.setf(ios::hex, ios::dec|ios::hex|ios::oct); return i; }inline ios& oct(ios& i){ i.setf(ios::oct, ios::dec|ios::hex|ios::oct); return i; }}

# 1 "hello.cc" 2

void main(){ cout << "Ciao!!!" << endl;}

Page 65: Introduzione al linguaggio C++ 5 lezioni Lunedì, Giovedì ore 12.00-13.30 Alessandro Lonardo alessandro.lonardo@roma1.infn.it Davide Rossetti davide.rossetti@roma1.infn.it.

hello.s (Assembly) .file "hello.cc"gcc2_compiled.:___gnu_compiled_cplusplus: .def ___terminate; .scl 2; .type 32; .endef .def ___sjthrow; .scl 2; .type 32; .endef .def ___main; .scl 2; .type 32; .endef.textLC0: .ascii "Ciao!!!\0" .align 4.globl _main .def _main; .scl 2; .type 32; .endef_main: pushl %ebp movl %esp,%ebp subl $8,%esp call ___main addl $-8,%esp pushl $LC0 pushl $_cout call ___ls__7ostreamPCc addl $16,%esp addl $-12,%esp pushl %eax call _endl__FR7ostream movl %ebp,%esp xorl %eax,%eax popl %ebp ret .def _endl__FR7ostream; .scl 2; .type 32; .endef .def ___ls__7ostreamPCc; .scl 3; .type 32; .endef

Page 66: Introduzione al linguaggio C++ 5 lezioni Lunedì, Giovedì ore 12.00-13.30 Alessandro Lonardo alessandro.lonardo@roma1.infn.it Davide Rossetti davide.rossetti@roma1.infn.it.

Il file eseguibile (hello.exe)

^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@<83><EC>^X<83>=^@ A^@^@t^A<CC><D9>}<FE>^O<B7>E<FE><B7>E<FE>^M?^C^@^@f<89>E<FE><D9>m<FE><83><C4><F4>h<C3><90><90><90>Ciao!!!^@U<89><E5><83><EC<E8>M<DA><C4><F8>hD^P@^@h$ A^@<E8><B3>^R^@^@<83><C4>^P<89><1<C0><EB>^A<90><89><EC>]<C3>U<89><E5><8B>;^U^D A^@<D2>t,<C7>^E<AC> A^@^@0A^@<C7>^E( A^@`0A^@<C7>^EhA^@<EB>*<89><F6><C7>^E<AC> A^@$!A^@<C7>^E( A^@<84><E8> A^@<E4>!A^@<A1>^D A^@<89>^U^D A^@<89><EC>]<C3:<95>^@^@<89><C3><83>}^L^@tJ<8B><83><C0<8B><89>^B<<C7>^@^@^@^@<C7>@^D^@^@^@^@<C7>^@^@^@^@f<C7>@^P ^@<C7>@^X^@^@^@^@<8B>C^D<8D>S^D<89>E<E0><C7>E<E4>^@^<84>^Q@^@<89><8D>M<E0><89><8B><8B>^B<C7>@^\<C4>%A^@<83>}^L^@u1<8D>}<C0><BE><<A5><8B>^B<8B><8D>U<C0><89>P^\<89><CA><8B>^A<83><C<D0>f<89>E<C8><8B><8B>^Q<83>}^P^@u <C6>B^R^D<<8B>E^P<89>^B<8B>E^T<89>B^D<C7>^@^@^@^@f<C7>B^P ^@<C7>B^X^@^@^@^@<8B><C7>B^D^@^@^@^@<8B>C^D<8B>^@<89<89><E5><83><EC>^TS<8B><89><F6><83><C4><F4>S<E8><F<FA><FF>t^L<A1><E0>@A^@<F6>D^P^u<E1><8B>]<E8><89><<EC>^TS<8B><8B>^C<8A>P^R<84><D2>t <80><CA>^B<C9>t^V<8B>^P<8B>B^D9u^L<83><C4><F4>Q<E8>^T^@^@<83><C4>^P<8B>^C<83><C4><F4><8B>^@P<E8><8E>A<8B>E^L<88>^P<C7>C^D^A^@^@^@<EB>^N<90><8B>^C<80>H^]<E8><89><EC>]<C3><89><F6>U<89><E5><83><EC>^PV<8B><FF><FF><FF><EB>Q<89><F6><8B>H^D<85><C9>t^V<8B>^P<<96>^S^@^@<83><C4>^P<8B>^F<8B>^X<8B>9C^Dr^N<83><C4<FF>t <8B>C^D^O<B6>^P<EB>^C<90><89><C2><83><FA><<8D>e<E8>[^<89><EC>]<C3>U<89><E5><83><EC>^LWVS<8B><8A>P^R<84><D2>t <80><CA>^B<88>P^R<EB>]<90>^D9u^L<83><C4><F4>Q<E8>^V^S^@^@<83><C4>^P<8B>^C<8B<E8><93>^^^@^@<89>C^D<EB>&<89><F6><8B>^C<80>H^R^C<^@<83><C4>^P<83><F8><FF>t<E4><FF>C^D;E^Pu<E4><8D>e

Page 67: Introduzione al linguaggio C++ 5 lezioni Lunedì, Giovedì ore 12.00-13.30 Alessandro Lonardo alessandro.lonardo@roma1.infn.it Davide Rossetti davide.rossetti@roma1.infn.it.

...che però si può disassemblare:

hello.exe: file format pei-i386

Disassembly of section .text:

00401000 <_mainCRTStartup>: 401000: 55 push %ebp 401001: 89 e5 mov %esp,%ebp 401003: 83 ec 18 sub $0x18,%esp 401006: 83 3d 00 20 41 00 00 cmpl $0x0,0x412000 40100d: 74 01 je 401010 <_mainCRTStar 40100f: cc int3 401010: d9 7d fe fnstcw 0xfffffffe(%ebp) 401013: 0f b7 45 fe movzwl 0xfffffffe(%ebp),%eax 401017: 25 c0 f0 ff ff and $0xfffff0c0,%eax 40101c: 66 89 45 fe mov %ax,0xfffffffe(%ebp) 401020: 0f b7 45 fe movzwl 0xfffffffe(%ebp),%eax 401024: 0d 3f 03 00 00 or $0x33f,%eax 401029: 66 89 45 fe mov %ax,0xfffffffe(%ebp) 40102d: d9 6d fe fldcw 0xfffffffe(%ebp) 401030: 83 c4 f4 add $0xfffffff4,%esp 401033: 68 4c 10 40 00 push $0x40104c 401038: e8 1b da 00 00 call 40ea58 <_cygwin_crt0> 40103d: 89 ec mov %ebp,%esp 40103f: 5d pop %ebp 401040: c3 ret 401041: 90 nop 401042: 90 nop 401043: 90 nop

00401044 <.text>: 401044: 43 inc %ebx 401045: 69 61 6f 21 21 21 00 imul $0x212121,0x6f(%ecx),%esp0040104c <_main>: 40104c: 55 push %ebp 40104d: 89 e5 mov %esp,%ebp 40104f: 83 ec 08 sub $0x8,%esp 401052: e8 4d da 00 00 call 40eaa4 <___main> 401057: 83 c4 f8 add $0xfffffff8,%esp 40105a: 68 d0 27 40 00 push $0x4027d0 40105f: 83 c4 f8 add $0xfffffff8,%esp 401062: 68 44 10 40 00 push $0x401044 401067: 68 24 20 41 00 push $0x412024 40106c: e8 b3 12 00 00 call 402324 <___ls__7os 401071: 83 c4 10 add $0x10,%esp 401074: 89 c0 mov %eax,%eax 401076: 50 push %eax

Page 68: Introduzione al linguaggio C++ 5 lezioni Lunedì, Giovedì ore 12.00-13.30 Alessandro Lonardo alessandro.lonardo@roma1.infn.it Davide Rossetti davide.rossetti@roma1.infn.it.

librerie

un insieme di file oggetto (.o) ottenuti compilando i corrispondentifile sorgente (.c, .cc) accompagnati da uno o più header file (.h)con le dichiarazioni per l'uso dei file .o

-supponiamo di voler scrivere una libreria per la crittografia DES, un possibile header file:

#ifndef _DESCRYPT_H_#define _DESCRYPT_H_

//necessario per utilizzare librerie C in C++//istruisce il linker sul modo di chiamata (ABI)extern "C" { void encrypt(char *block, int edflag); void setkey(char *key); char* crypt(const char *key, const char *salt);}#endif

-supponiamo di aver definito queste funzioni nei rispettivi file C:encrypt.c setkey.c crypt.c

-ad esempio lavorando su un sistema UNIX, la seguente serie dicomandi genera la libreria descrypt.a:

$ cc -c encrypt.c setkey.c crypt.c$ ar cr descrypt.a encrypt.o setkey.o crypt.o$ ranlib descrypt.a

Page 69: Introduzione al linguaggio C++ 5 lezioni Lunedì, Giovedì ore 12.00-13.30 Alessandro Lonardo alessandro.lonardo@roma1.infn.it Davide Rossetti davide.rossetti@roma1.infn.it.

posso ispezionare il contenuto di una libreria (implementazioni vuote!):

$ nm -s descrypt.a

Archive index:_encrypt in encrypt.o_setkey in setkey.o_crypt in crypt.o

encrypt.o:00000000 b .bss00000000 d .data00000000 t .text00000000 t ___gnu_compiled_c00000000 T _encrypt00000000 t gcc2_compiled.

setkey.o:00000000 b .bss00000000 d .data00000000 t .text00000000 t ___gnu_compiled_c00000000 T _setkey00000000 t gcc2_compiled.

crypt.o:00000000 b .bss00000000 d .data00000000 t .text00000000 t ___gnu_compiled_c00000000 T _crypt00000000 t gcc2_compiled.

Page 70: Introduzione al linguaggio C++ 5 lezioni Lunedì, Giovedì ore 12.00-13.30 Alessandro Lonardo alessandro.lonardo@roma1.infn.it Davide Rossetti davide.rossetti@roma1.infn.it.

-uso della libreria:

nella mia applicazione (secure_link.cc) includerò il file header che corrisponde alla libreria e farò chiamate alle funzioni là definite

#include "descrypt.h"//...setkey(sessionkey);mycrypt = crypt(sessionkey, sugar);//...

-per compilare la mia applicazione:

$ c++ secure_link.cc descrypt.a -o secure_link

in questo modo il linker estrae i file .o dalla libreria e li collega conil file secure_link.o garantendo che venga fornita la definizione delle funzioni di libreria richiamate in secure_link.cc

-librerie dinamiche (.so sotto UNIX, .dll sotto WINDOWS): vengono incluse al momento della esecuzione, dimensioni ridotte degli eseguibili.

-riutilizzo del codice

Page 71: Introduzione al linguaggio C++ 5 lezioni Lunedì, Giovedì ore 12.00-13.30 Alessandro Lonardo alessandro.lonardo@roma1.infn.it Davide Rossetti davide.rossetti@roma1.infn.it.

classi

una classe (class) è un tipo definito dall'utente

e le struct allora?

anche loro!

//definisco il tipostruct Date { int day, month, year; };//definisco le operazioni sul tipovoid set_date(date*, int, int, int);void get_date(date*, int&, int&, int&);void tomorrow_date(date*);void yesterday_date(date*);void print_date(const date*);

-è un pò scomodo, non c'è un legame tra le funzioni ed il tipo (se nonnei parametri e nel nome scelto opportunamente)

-una cosa che ancora non vi avevo detto a proposito delle struct:

struct Date{ int day, month, year; //dichiarazione metodi (o funzioni proprie) void set(int, int, int); void get(int&, int&, int&); void tomorrow(); void yesterday(); void print();};

Page 72: Introduzione al linguaggio C++ 5 lezioni Lunedì, Giovedì ore 12.00-13.30 Alessandro Lonardo alessandro.lonardo@roma1.infn.it Davide Rossetti davide.rossetti@roma1.infn.it.

-i metodi possono essere richiamati solo per una variabile deltipo che gli compete:

Date today, xmas;//...today.set(24, 7, 2001);xmas.set(25, 12, 2001);today.tomorrow();xmas.print();today.print();

-definizione di un metodo:

void Date::tomorrow(){ if(++day > 28) //trentagiornihanovembrecon...}

Date:: è necessario, potrei aver dichiarato il metodo void tomorrow() anche per un altra struct

-rimane l'imbarazzante capacità di modificare lo stato interno deltipo Date manipolando direttamente i suoi campi (e non per mezzodelle operazioni implementate dai metodi):

today.day = today.month = today.year = -13;

e allora entrano in gioco le classi!

l'operatore discope resolution!

Page 73: Introduzione al linguaggio C++ 5 lezioni Lunedì, Giovedì ore 12.00-13.30 Alessandro Lonardo alessandro.lonardo@roma1.infn.it Davide Rossetti davide.rossetti@roma1.infn.it.

class Date{ int day, month, year;public: void set(int, int, int); void get(int&, int&, int&); void tomorrow(); void yesterday(); void print();};

-i nomi contenuti nella parte privata possono essere manipolati solodai metodi della classe

-la parte pubblica è anche detta interfaccia agli oggetti della classe

-in tutte le parti possono essere presenti sia dati(attributi) che funzioni(metodi)

Oggetto = istanza di una classe. Identificato dal nome, definisce uno stato che è rappresentato dal valore dei suoi attributi a un certo istante di tempo.

int i;

int è la classe (il tipo)i è il nome dell'oggetto(variabile)

parte privata

parte pubblica

Page 74: Introduzione al linguaggio C++ 5 lezioni Lunedì, Giovedì ore 12.00-13.30 Alessandro Lonardo alessandro.lonardo@roma1.infn.it Davide Rossetti davide.rossetti@roma1.infn.it.

encapsulation: nascondere tutti i dettagli di un oggetto che non contribuiscono in maniera essenziale alle sue caratteristiche(esposte tramite l'interfaccia)

-una struct è una classe in cui tutti i membri sono pubblici.

void Date::print(){ cout << day << '/' << month << '/' << year;}

va tutto bene, Date::print è un metodo della classe Dateed ha accesso alla sua parte privata.

void print_date(Date day){ cout << day.day << '/' << day.month

<< '/' << day.year;}

non va bene, la funzione print_date non può leggere gli attributiprivati di un oggetto della classe Date

Page 75: Introduzione al linguaggio C++ 5 lezioni Lunedì, Giovedì ore 12.00-13.30 Alessandro Lonardo alessandro.lonardo@roma1.infn.it Davide Rossetti davide.rossetti@roma1.infn.it.

dichiarazione di una classe:

// in particle.hclass Particle {private: // chi lo può chiamare ?

void SetMass(double m); protected:

Vector q; //attributi Vector p; //o variabili membroint charge;double mass;

public: Particle(const Vector& q, //un costruttore const Vector& p, int charge, double mass);

~Particle(); //un distruttore

double GetMass() const //un metodo{ return this->mass; }

};

Page 76: Introduzione al linguaggio C++ 5 lezioni Lunedì, Giovedì ore 12.00-13.30 Alessandro Lonardo alessandro.lonardo@roma1.infn.it Davide Rossetti davide.rossetti@roma1.infn.it.

-protected: meno privata di private, vedremo parlando di classiderivate.

-costruttore: metodo per l'inizializzazione degli oggetti,ha lo stesso nome della classe

-distruttore: metodo richiamato quando un oggetto esce dallo scopein cui è stato dichiarato, la memoria da esso occupata viene liberata.Il distruttore per la classe T si chiama ~T()

-metodo const: può leggere ma non modificare l'oggetto per cui vienerichiamata

-this: nome sempre disponibile nei metodi, per una classe T è ditipo T* e rappresenta il puntatore all'oggetto di invocazione

-inlining: defininendo metodi nella dichiarazione della classe questisaranno automaticamente considerate dal compilatore come funzioniinline (comodo per metodi "piccoli" richiamati di frequente)

Page 77: Introduzione al linguaggio C++ 5 lezioni Lunedì, Giovedì ore 12.00-13.30 Alessandro Lonardo alessandro.lonardo@roma1.infn.it Davide Rossetti davide.rossetti@roma1.infn.it.

-implementazione della classe:

// in particle.ccParticle::Particle(const Vector& q, const Vector& p, int c, double mass){

m_q = q; m_p = p;m_charge = c;m_mass = mass;

}

void Particle::SetMass(double mass){ this->m_mass = mass; // this-> e` opzionale}

-this e` una varibile sempre disponibile dentro l’implementazione di ogni metodo di una classe; e` di tipo NOME_CLASS* in questo caso Particle* .

Più precisamente: Particle* const this

E` come se ogni metodo avesse un ulteriore parametro nascosto che serve per accedere ai membri del nostro oggetto.

-utile per le classi contenitore: alberi, liste...

Page 78: Introduzione al linguaggio C++ 5 lezioni Lunedì, Giovedì ore 12.00-13.30 Alessandro Lonardo alessandro.lonardo@roma1.infn.it Davide Rossetti davide.rossetti@roma1.infn.it.

Interfaccia-Implementazione

Classe = scatola nera su cui si agisce per mezzo di un certo insiemedi operazioni (interfaccia)

Fintanto che l'interfaccia è fissata, la effettiva realizzazione dellaclasse (implementazione) può subire dei cambiamenti senza chel'utente della classe se ne accorga.

-static: questo è uno dei nomi più sovraccaricati di significati nel mondo dei linguaggi di programmazione (lo abbiamo già incontrato).Quando lo si usa nella dichiarazione di un membro di una classe significa:membro comune a tutti gli oggetti della classe

class Elettrone{static double massa;static int carica;

protected:Vector q; Vector p;

};//...double Elettrone::mass = 9.1091e-31;int Elettrone::carica = -1;//...-anche i metodi possono essere dichiarati static

Page 79: Introduzione al linguaggio C++ 5 lezioni Lunedì, Giovedì ore 12.00-13.30 Alessandro Lonardo alessandro.lonardo@roma1.infn.it Davide Rossetti davide.rossetti@roma1.infn.it.

Un esempio

file geom.h:

class Mat_3_3; //forward declaration

//realizza un vettore 3Dclass Vett_3{protected: double v[3]; public: Vett_3(double x = 0.0, double y = 0.0, double z = 0.0) { v[0] = x; v[1] = y; v[2] = z; } void Stampa(); //modulo del vettore double Mod(); //moltiplicazione per matrice 3x3 Vett_3 Molt(const Mat_3_3& );

//overload dell'operatore somma //è parte dell'interfaccia, //anche se non è un metodo friend Vett_3 operator*(const double, const Vett_3&);

friend Vett_3 operator+(const Vett_3& , const Vett_3&);};

Page 80: Introduzione al linguaggio C++ 5 lezioni Lunedì, Giovedì ore 12.00-13.30 Alessandro Lonardo alessandro.lonardo@roma1.infn.it Davide Rossetti davide.rossetti@roma1.infn.it.

//realizza una matrice 3x3class Mat_3_3{ double m[3][3];public: Mat_3_3(double m00 = 0.0,

double m01 = 0.0, double m02 = 0.0, double m10 = 0.0, double m11 = 0.0, double m12 = 0.0, double m20 = 0.0, double m21 = 0.0, double m22 = 0.0);

void Stampa(); //è parte dell'interfaccia, //anche se non è un metodo di Mat_3_3 friend Vett_3 Vett_3::Molt(const Mat_3_3& m);};

Page 81: Introduzione al linguaggio C++ 5 lezioni Lunedì, Giovedì ore 12.00-13.30 Alessandro Lonardo alessandro.lonardo@roma1.infn.it Davide Rossetti davide.rossetti@roma1.infn.it.

-friend: una funzione (anche come nel nostro esempio deglioperatori e delle funzioni membro) che ha accesso alla parte privata di una classe. Dal momento che può manipolare liberamente gli oggetti di una classeè opportunamente inserita nella dichiarazione della classe (nellainterfaccia).

class A{ friend class B; //...};

-il senso della dichiarazione è che tutti i metodi di B sono funzionifriend di A.

-gli operatori sono spesso dichiarati friend

L'operatore visto prima:

friend Vett_3 operator*(const double, const Vett_3&);

nella sua definizione avrà libero accesso alla parte privata degli oggettidella classe Vett_3.

L'operatore accetta const Vett_3& come secondo parametro perchè non deve modificarlo ma allo stesso tempo il compilatorenon devrà fare una copia del parametro.

Page 82: Introduzione al linguaggio C++ 5 lezioni Lunedì, Giovedì ore 12.00-13.30 Alessandro Lonardo alessandro.lonardo@roma1.infn.it Davide Rossetti davide.rossetti@roma1.infn.it.

-file geom.cc;

#include <math.h>#include <iostream.h>#include "geom.h"

//metodi ed operatori di Vett_3

void Vett_3::Stampa() { cout << "(" << v[0] << '\t' << v[1] << '\t' << v[2] << ")" << endl; }

double Vett_3::Mod(){ double ris = sqrt( v[0]*v[0] + v[1]*v[1] + v[2]*v[2] ); return ris;}

Vett_3 Vett_3::Molt(const Mat_3_3& mat){ Vett_3 ris;

for(int i = 0; i < 3; i++) { for(int j = 0; j < 3; j++)

ris.v[i] += mat.m[i][j] * v[i]; }

return ris;}

Page 83: Introduzione al linguaggio C++ 5 lezioni Lunedì, Giovedì ore 12.00-13.30 Alessandro Lonardo alessandro.lonardo@roma1.infn.it Davide Rossetti davide.rossetti@roma1.infn.it.

//quelli che seguono non sono metodi di Vett_3

Vett_3 operator*(const double op1, const Vett_3& op2){ Vett_3 ris; for(int i = 0; i < 3; i++) ris.v[i] = op1 * op2.v[i]; //!!!Friend!!!

return ris;}

Vett_3 operator+(const Vett_3& op1, const Vett_3& op2){ Vett_3 ris; for(int i = 0; i < 3; i++) ris.v[i] = op1.v[i] + op2.v[i];//idem return ris;}

Page 84: Introduzione al linguaggio C++ 5 lezioni Lunedì, Giovedì ore 12.00-13.30 Alessandro Lonardo alessandro.lonardo@roma1.infn.it Davide Rossetti davide.rossetti@roma1.infn.it.

//metodi di Mat_3_3Mat_3_3::Mat_3_3(double m00 = 0.0, double m01 = 0.0, double m02 = 0.0,

double m10 = 0.0, double m11 = 0.0, double m12 = 0.0,

double m20 = 0.0, double m21 = 0.0, double m22 = 0.0){ m[0][0] = m00; m[0][1] = m01; m[0][2] = m02; m[1][0] = m10; m[1][1] = m11; m[1][2] = m12; m[2][0] = m20; m[2][1] = m21; m[2][2] = m22;}

void Mat_3_3::Stampa(){ for(int i = 0; i < 3; i++) { for(int j = 0; j < 3; j++)

cout << m[i][j] << 't'; cout << endl; }}

Page 85: Introduzione al linguaggio C++ 5 lezioni Lunedì, Giovedì ore 12.00-13.30 Alessandro Lonardo alessandro.lonardo@roma1.infn.it Davide Rossetti davide.rossetti@roma1.infn.it.

#include <iostream.h>#include "geom.h"

#define PI 3.14159265358979323846

void main(){ Vett_3 x(0.0, 3.0, 4.0); cout << "X:\t"; x.Stampa(); cout << "Modulo(X): " << x.Mod() << endl; Vett_3 y(0.0, -5.0, 3.0); Vett_3 z = 2.0 * (x + y); cout << "Z:\t"; z.Stampa();

double theta = PI/4.0; double phi = PI/4.0; Mat_3_3 Mat(cos(phi), -sin(phi), 0.0,

sin(phi), cos(phi), 0.0, 0.0 , 0.0, 1.0);

cout << "Mat:" << endl; Mat.Stampa();

Vett_3 z_phi = z.Molt(Mat);

cout << "z_phi:\t"; z_phi.Stampa();

Page 86: Introduzione al linguaggio C++ 5 lezioni Lunedì, Giovedì ore 12.00-13.30 Alessandro Lonardo alessandro.lonardo@roma1.infn.it Davide Rossetti davide.rossetti@roma1.infn.it.

-ottengo:

$ ./geotest.exeX: (0 3 4)Modulo(X): 5Z: (0 -4 14)Mat:0.707107 -0.707107 00.707107 0.707107 00 0 1z_phi: (0 -5.65685 14)

Page 87: Introduzione al linguaggio C++ 5 lezioni Lunedì, Giovedì ore 12.00-13.30 Alessandro Lonardo alessandro.lonardo@roma1.infn.it Davide Rossetti davide.rossetti@roma1.infn.it.

-supponiamo di voler introdurre un nuovo tipo di dato che rappresentiun versore in 3 dimensioni.

Potrei dichiararlo nella seguente maniera:

class Vers_3{protected: double v[3]; public: Vers_3(double x = 0.0, double y = 0.0, double z = 0.0); void Stampa(); //modulo del versore, si spera = 1.0 double Mod(); //moltiplicazione per matrice 3x3 Vers_3 Molt(const Mat_3_3& );

friend Vers_3 operator*(const double, const Vers_3&);

friend Vers_3 operator+(const Vers_3& , const Vers_3&);};

Somiglia tantissimo alla dichiarazione del Vett_3: i dati sono gli stessi,le operazioni pure, anche se alcune sono modificate nel comportamento: Costruttore, Mod()...

Page 88: Introduzione al linguaggio C++ 5 lezioni Lunedì, Giovedì ore 12.00-13.30 Alessandro Lonardo alessandro.lonardo@roma1.infn.it Davide Rossetti davide.rossetti@roma1.infn.it.

-rendo esplicito quello che le classi Vett._3 e Vers_3 hanno incomune utilizzando il meccanismo della derivazione di classi-file geom.h:

class Vers_3 : public Vett_3{ public: //crea un versore Vers_3(double x, double y, double v); //converte in Vett_3 in un Vers_3 Vers_3(const Vett_3& v3); //crea un versore da coordinate sferiche Vers_3(double theta, double phi); //lo sto ridefinendo rispetto alla classe base void Stampa();};

Vers_3 specializza la classe Vett_3 al concetto di versore.

Vers_3 è una classe derivata publicamente da Vett_3. Eredita tutti i dati e le funzioni di Vett_3 dichiarate public o protected.

Vett_3 è una classe di base per Vers_3.

-importante: è possibile assegnare ad un puntatore a Vett_3 un puntatore ad un oggetto Vers_3 senza dover fare il cast esplicito (conversione).

Utilizzando i puntatori si può trattare un oggetto di una classe derivatacome se fosse un oggetto della classe di base.

Page 89: Introduzione al linguaggio C++ 5 lezioni Lunedì, Giovedì ore 12.00-13.30 Alessandro Lonardo alessandro.lonardo@roma1.infn.it Davide Rossetti davide.rossetti@roma1.infn.it.

-file geom.cc:

Vers_3::Vers_3(double x = 0.0, double y = 0.0, double z = 0.0) : Vett_3(x, y, z){ double inv_mod = 1.0/Mod();

v[0] = inv_mod * v[0]; v[1] = inv_mod * v[1]; v[2] = inv_mod * v[2];}

Vers_3::Vers_3(const Vett_3& v3) : Vett_3(v3) { double inv_mod = 1.0/Mod();

v[0] = inv_mod * v[0]; v[1] = inv_mod * v[1]; v[2] = inv_mod * v[2];} Vers_3::Vers_3(double theta, double phi){ v[0] = sin(theta) * cos(phi); v[1] = sin(theta) * sin(phi); v[2] = cos(theta);}

void Vers_3::Stampa() { cout << "<" << v[0] << '\t' << v[1] << '\t' << v[2] << ">" << endl; }

Page 90: Introduzione al linguaggio C++ 5 lezioni Lunedì, Giovedì ore 12.00-13.30 Alessandro Lonardo alessandro.lonardo@roma1.infn.it Davide Rossetti davide.rossetti@roma1.infn.it.

costrutore: ho richiamato il costuttore della classe di base nel costruttore della classe derivata.Sto trattando la classe di base come un oggetto proprio della classederivata.

-ordine di costruzione: classe di base, elementi, classe derivata

-ordine di distruzione: classe derivata, elementi, classe di base

-Nei costruttori ho richiamato il metodo Mod(), chi era l'oggettod'invocazione?

Page 91: Introduzione al linguaggio C++ 5 lezioni Lunedì, Giovedì ore 12.00-13.30 Alessandro Lonardo alessandro.lonardo@roma1.infn.it Davide Rossetti davide.rossetti@roma1.infn.it.

-uso:

#include <iostream.h>#include "geom.h"

#define PI 3.14159265358979323846

void main(){ Vers_3 versore(PI/4.0, PI/4.0); cout << "versore(PI/4.0, PI/4.0):" << endl; versore.Stampa();//quale Stampa() chiama?

double theta = PI/4.0; double phi = PI/4.0; Mat_3_3 Mat(cos(phi), -sin(phi), 0.0,

sin(phi), cos(phi), 0.0, 0.0 , 0.0, 1.0);

//ma come, molt non era un metodo di Vett_3 //che restituiva un Vett_3??? Vers_3 ris = versore.molt(Mat); cout << "...dopo una rotazione di PI/4.0 lungo l'asse Z:" << endl; ris.Stampa();}

Page 92: Introduzione al linguaggio C++ 5 lezioni Lunedì, Giovedì ore 12.00-13.30 Alessandro Lonardo alessandro.lonardo@roma1.infn.it Davide Rossetti davide.rossetti@roma1.infn.it.

-ottengo:

$ ./geotest.exeversore(PI/4.0, PI/4.0):<0.5 0.5 0.707107>...dopo una rotazione di PI/4.0 lungo l'asse Z:<3.92481e-17 0.707107 0.707107>

è stato richiamato Vers_3::Stampa(), come probabilmente ci aspettavamo.

Ma se avessi scritto: //... Vers_3 ris = versore.Molt(Mat); Vett_3* pv = &ris;//si può fare! cout << "...dopo una rotazione di PI/4.0 lungo l'asse Z:" << endl; pv->Stampa(); //...

-avrei ottenuto:

$ ./geotest.exeversore(PI/4.0, PI/4.0):<0.5 0.5 0.707107>...dopo una rotazione di PI/4.0 lungo l'asse Z:(3.92481e-17 0.707107 0.707107)

brutto!

Page 93: Introduzione al linguaggio C++ 5 lezioni Lunedì, Giovedì ore 12.00-13.30 Alessandro Lonardo alessandro.lonardo@roma1.infn.it Davide Rossetti davide.rossetti@roma1.infn.it.

il C++ prevede la soluzione di questo problema tramite la keywordvirtual

Basta aggiungere questa parola chiave nella dichiarazione dei metodidella classe di base che si vogliono ridefinire nelle classi derivate:

class Vett_3{protected: double v[3]; public: //... virtual void Stampa(); //...};

con questa modifica otterremo:

$ ./geotest.exeversore(PI/4.0, PI/4.0):<0.5 0.5 0.707107>...dopo una rotazione di PI/4.0 lungo l'asse Z:<3.92481e-17 0.707107 0.707107>

polimorfismo!

Page 94: Introduzione al linguaggio C++ 5 lezioni Lunedì, Giovedì ore 12.00-13.30 Alessandro Lonardo alessandro.lonardo@roma1.infn.it Davide Rossetti davide.rossetti@roma1.infn.it.

controllo dell'accesso

-private: il nome può essere usato solo dai metodi e dalle funzioni amiche della classe.

-protected: il nome può essere usato solo dai metodi e dalle funzioniamiche della classe e delle classi derivate

-public: il nome è utilizzabile da qualunque funzione

variabile utente

public

protected

private

ok

Page 95: Introduzione al linguaggio C++ 5 lezioni Lunedì, Giovedì ore 12.00-13.30 Alessandro Lonardo alessandro.lonardo@roma1.infn.it Davide Rossetti davide.rossetti@roma1.infn.it.

Nell'esempio abbiamo visto una derivazione public.In realtà (anche se si usa raramente) si può fare anche una derivazioneprotected o private --> Manuale!

variabilederivazionepublic

derivazioneprotected

derivazioneprivate

public public protected private

protected protected protected private

private

nella classe derivataclassebase

Page 96: Introduzione al linguaggio C++ 5 lezioni Lunedì, Giovedì ore 12.00-13.30 Alessandro Lonardo alessandro.lonardo@roma1.infn.it Davide Rossetti davide.rossetti@roma1.infn.it.

Memoria dinamica

operatori New e Delete

-finora abbiamo creato oggetti automatici (sullo stack) o a livello file:

char *bubu;int ciccio;...void funzione(){

int anni = 0;//...

-ma si puo` fare allocazione dinamica: // chiama costruttore Vers_3* pv = new Vers_3(theta,phi); //... pv->Stampa(); //... delete pv; // qui viene chiamato

// il distruttore

Page 97: Introduzione al linguaggio C++ 5 lezioni Lunedì, Giovedì ore 12.00-13.30 Alessandro Lonardo alessandro.lonardo@roma1.infn.it Davide Rossetti davide.rossetti@roma1.infn.it.

-gli oggetti dinamici hanno vita fino alla distruzione esplicita con

delete

-si possono creare dinamicamente tutti i tipi , base, composti o classi:int *index = new int(1123);double *num = new double;*num = 12.34;int j = *index;delete index; delete num;

-pure vettori, ma attenti ai costruttori con parametri e al delete:

int* vec = new int[100];

Triangle* t1 = new Triangle[20]; //no params

vec[33] = 23;

//…

delete [] vec;