C/C++
Claudio Rocchini
IGM
C. Rocchini - C++
1
-1 Pre Introduzione
C. Rocchini - C++
2
Il C/C++
• Il C++ e’ un linguaggio di programmazione.
• E’ il lunguaggio utilizzato per creare i
programmi (insieme all’Assembler), (es.
Windows, Linux, Office, OpenOffice, Apache,
Perl, PHP, Oracle, PostgreSql, AdobePhotoshop,
etc. sono scritti un C/C++)
• L’efficienza e’ uno degli obiettivi principali
(supporto run-time minimo, contrapposto a Java,
Basic, PHP, Perl : support RE massimo +
garbage-collector).
• Ma e’ anche un linguaggio molto espressivo.
• Nasce in ambiente industriale (non accademico o
umanistico).
C. Rocchini - C++
3
0 - Introduzione
C. Rocchini - C++
4
Il Mio primo programma
#include <stdio.h>
//libreria stdio
int main()
{
printf(“Buongiorno”);
return 0;
}
//funzione principale
//Inizio blocco
//Stampa buongiorno
//Riturna il valore 0
//Fine blocco
// La spaziatura non conta
// Tutto i comandi finiscono con ;
// I bocchi sono delimitati da {}
C. Rocchini - C++
5
Struttura
TipoRisultato NomeFunzione( Parametri)
{
istruzione;
istruzione;
…
return valore_ritorno;
}
Altra_Funzione …
// Commento di una linea
/* Commento di piu’
linee */
C. Rocchini - C++
6
Nota sullo stile
• La spaziatura, la tabulazione e i ritorni a
capo non hanno alcun significato (al contrario
del Basic o del Fortran).
• Questo non vuol dire che bisogna scrivere
disordinatamente.
• Di solito si indenta (tabularizza) i blocchi
fra parentesi per facilitare la lettura.
• I nomi devono essere significativi.
C. Rocchini - C++
7
Nota sullo stile 2
• Esiste un campionato mondiale di C scritto
disordinato: “The International Obfuscated C
Code Contest”, http://www.ioccc.org/
• Uno dei vincitori:
main() { printf(&WIN32["\021%six\012\0"],(WIN32)["have"]+"fun"-0x60);}
C. Rocchini - C++
8
Nota sullo stile 3
#define _ F-->00||F-OO--;
int F=00,OO=00;main(){F_OO();printf("%1.3f\n",4.*-F/OO/OO);}F_OO()
{
_-_-_-_
_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_
_-_-_-_
}
C. Rocchini - C++
9
Esercitazione
• Es0: applicazione console
• Consultate i lucidi relativi
alla esercitazione 0:
applicazione console
C. Rocchini - C++
10
4 – Tipi Fondamentali
C. Rocchini - C++
11
Tipi fondamentali
float x;
// x e’ una variabile in virgola mobile
// in Basic: dim x as single
int y = 7;
// y e’ una var. intera con valore iniz. 7
float fun(int x); // fun e’ una funzione da float a int
// in Basic: function fun( x as integer ) as single
char c;
// c e’ un carattere
double z;
// z e’ una variabile in doppia precisione
// void = tipo “nullo” esempio:
void sub(); // sub e’ una procedura (subroutine)
C. Rocchini - C++
12
Costruire Altri Tipi
int * punt;
// Puntatore ad intero
char vet[7];
// Vettore di caratteri
double & d;
// “Riferimento” ad un double
// Enumerazioni
enum giorni { lunedi, martedi, mercoledi, … };
// Strutture:
struct Coordinata
{
double latitudine;
double longitudine;
}; // In basic: structure
// Classi… (come vedremo piu’ avanti)
C. Rocchini - C++
13
Bool (Valore di verità)
bool x = true;
bool y = false;
// Variabile inizializzata
int a = 1;
int b = 1;
bool k = a==b;
// a e’ uguale a b?
bool q = (a!=0) && (b>7);
// Diverso, maggiore
C. Rocchini - C++
14
Char (carattere)
char c = ‘a’;
char k = 32;
// Carattere letterale
// Conversione da codice ascii
int c = int(‘$’);
// Conversione in codice ascii
if( isupper(c) ) .. // Esempio di funzioni
bool k = isdigit(k);
// k e’ una cifra (0-9)
// Nota: da non confondersi con string!
C. Rocchini - C++
15
Tipi interi
int a = 3;
short int s;
short s;
long int l;
long l;
unsigned int u;
unsigned u;
unsigned long lu;
//
//
//
//
//
//
//
//
Intero standard(4-8 byte)
Intero a 2-4 byte
Scrittura abbreviata
Intero 4-8 byte
Scrittura abbreviata
Intero senza segno
Scrittura abbreviata
Intero lungo positivo
int x = 3*5+7-4/2;
// Espressioni
int k = 15%7; // =1, operatore modulo = resto divisione
int k = 0xFE;
// Costanti esadecimali
C. Rocchini - C++
16
Virgola mobile
float x = 1;
double y = 3.14;
double z = 1.2e10;
// Singola precisione
// Doppia precisione
// Notazione esponensiale
// Espressioni e funzioni
double t = 3*7-sqrt(k)+sin(9);
double z = 3^y;
// Esponenziale
int round = int(z+0.5);
int trunc = int(z);
// Arrotondamento ad intero
// Troncamento ad intero
C. Rocchini - C++
17
void
void x;
// Variabile nulla: VIETATO
void sub();
// Procedura (non ritorna niente)
void * p;
// Puntatore a qualcosa: utile per
// dichierare puntatori generici di
// tipo sconosciuto.
C. Rocchini - C++
18
Tipi Enumerati
enum e1 { LUN, MAR, MER, GI };
enum e2 { A=2, B, C, D };
enum e3 { K=1, H=99 };
// Non specificata
// Inizio specificato
// Tutti specificati
enum e1 pippo;
int x = MAR;
// Variabile di tipo enum
// Utilizzo del valore cost.
switch(pippo)
{
case LUN: …
// Utilizzo tipico: case
LUN = 99;
// Errore!
C. Rocchini - C++
19
Introduzione ai puntatori
int a = 5;
// Una variabile intera
int *p = &a;
// p è un puntatore a intero,
// viene assegnato all’indirizzo
// di a.
a = 6;
*p = 7;
// a ora vale 7
Cella di Memoria di a
Valore = 5
…
…
“Indirizzo” in memoria della cella:
Il puntatore alla cella.
int * q = 0; // 0, valore speciale
// Puntatore nullo
C. Rocchini - C++
20
Costanti
const double PI = 3.141596;
PI = 4;
// Valore costante
// Errore!
const char * p;
*p = ‘w’;
p = 0;
// Il contenuto e’ costante
// Errore
// OK
char * const p;
*p = ‘w’;
p = 0;
// Il puntatore e’ costante
// OK
// Errore
C. Rocchini - C++
21
Vettori Statici
char v[10];
int x;
v[7] = 11;
v[999] = 1;
// Vettore di 10 elemeni (da 0 a 9)
double mat[3][3];
mat[0][2] = 9;
//
//
//
//
//
Accesso ad un elemento
Errore catastrofico!
Forse distruggi x
Vettore bidimensionale
Accesso ad un elemento
char *p = &(v[0]);
char *p =
v;
// Indirizzo del primo elem.
// Scrittura abbreviata
int a = fun(); char w[a];
const int b = 10; char x[b];
C. Rocchini - C++
// Errore, dinamico
// Ok, statico
22
Dichiarazioni Multiple
int a,b,c;
// Tre interi
char k, *p;
// Un carattere ed un puntatore
bool y,v[11];
// Un booleano ed un vettore
C. Rocchini - C++
23
Regole di Visibilità
int x = 1;
// Globale al modulo
void sub()
{
x = 7;
// Modifico la globale
int x = 2;
// Locale alla procedura
…
{
int x = 3;
// Locale al sottoblocco
// Qui x vale 3
int y = 99;
}
// Qui y non e’ dichiarata!
}
C. Rocchini - C++
24
typedef
unsigned long * p;
// Puntatore ad intero lungo s.s.
typedef unsigned long * Pointer; // Definizione di tipo
Pointer p;
// Stesso tipo di p
typedef double Matrix[9][9];
Matrix m;
m[2][1] = 3;
C. Rocchini - C++
// Tipo matrice 9x9
// Dichiarazione
25
Strutture
struct Registrazione
{
bool ok;
int valore;
double x;
};
// Dichierazione di tipo
Registrazione r;
// Dichiarazione variabile
r.valore = 3;
r.x = 4.5;
// Utilizzo
// Notare il punto e virgola
C. Rocchini - C++
26
Strutture 2
struct Dipendente
{
string nome;
string cognome;
int eta;
};
…
Dipendete d1,d2;
d1.nome = “claudio”;
d1.eta = 37;
d2.nome = “claudia”;
C. Rocchini - C++
27
Puntatore a Strutture
struct Registrazione
{
bool ok;
int valore;
double x;
};
Registrazione a;
Registrazione * p = &a;
a.valore = 5;
(*p).valore = 3;
p->valore = 7;
// Dichierazione di tipo
// Notare il punto e virgola
// Una struttura
// Puntatore a struttura
// Accesso ai campi
// Altra scrittura
Registrazione k = {false,3,0.9}; // Inizializzazione
C. Rocchini - C++
28
Operatore “sizeof”
// restituisce la dimensione in byte di una variabile
sizeof(char)
// = 1
sizeof(short)
// = 2
sizeof(int)
// = 2 o 4
sizeof(long)
// = 4 o 8
sizeof(double)
// = 8
sizeof(char *)
// = 4 (ma 8 proc. 64 bit)
sizeof(double *)
// = sempre 4!
sizeof(void *)
// = sempre 4!
sizeof(short[32])
// = 64
C. Rocchini - C++
29
Sizeof(2)
struct registrazione
{
short x;
bool
b;
double y;
};
sizeof(registrazione)
// >= sizeof(short)+sizeof(bool)+sizeof(double)
// Attenzione! Puo’ essere anche maggiore per
// motivi di allineamento del processore
C. Rocchini - C++
30
La notte del C: le stringhe C
// Prima nota: ogni volta che e’ possibile si usi il
// tipo C++ std::string (e’ un oggetto)
// Stringhe letterali: incluse in virgolette
“questa e’ una stringa”
// I caratteri invece sono inclusi in apici
‘a’
// I vettori di caratteri possono essere interpretati
// come stringhe, le stringhe sono terminate dal
// carattere 0
char nome[100];
C. Rocchini - C++
31
Stringhe C (2)
char s[16] = “casa”;
// Inizializzazione
s[0]==‘c’
s[3]==‘a’
s[4]== 0
// Terminazione della stringa
s[5]== ??? Valore non Definito ???
char n1[4] = “casa”;
char n2[5] = “casa”;
sizeof(“casa”)==5
// Stringha nulla: “”
char nulla[1000] = “”;
nulla[0] == 0
// Errore: manca spazio
// OK: corretto
// 4 lettere + terminatore
// Subito il terminatore
C. Rocchini - C++
32
String C (3)
// I puntatori a carattere possono essere associati
// a stringhe (puntatori al primo carattere).
char * p = “cavallo”;
char x = p[2];
p[3] = ‘i’;
// Stringa costante !
// OK: lettura di ‘v’
// Errore: stringa costante
char str[32] = “cavallo”;
p = str;
p[3] = ‘i’;
// Stringa variabile
// p punta all’inizio di str
// OK: str = “cavillo”
C. Rocchini - C++
33
Stringhe C: funzioni
// Funzioni della libreria
int strlen( char * str);
//
str1 = str2;
//
strcpy( str1, str2 )
//
strcat( str1, str2 )
//
str1 == str2
//
strcmp( str1, str2 )
//
strchr( str1, char )
//
strstr( str1, str2 )
//
string.h
Lunghezza di una stringa
Errore!
Copia di stringhe
Concatenzazione
Errore! Conf. Puntatori!
Confronto fra stringhe
Cerca un carattere
Cerca una sottostringa
// Altre funzioni: tokenizzatore (parser)
strtok( str1, “separatori”)
C. Rocchini - C++
34
Stringhe, per finire: escape seq.
“\””
‘\’’
// Virgolette nelle stringhe
// Il carattere apicetto
“\n”
“\r”
“\t”
“\\”
//
//
//
//
Ritorno a capo
Ritorno carrello
Carattere di tabulazione
Caratte barra rovesciata
C. Rocchini - C++
35
6 – Espressioni ed Istruzioni
C. Rocchini - C++
36
Riepilogo operatori
A = 3;
// Aritmetica di
A = b+c;
A = b-c;
A = b*c;
A = b/c;
A = b%c;
A = -b;
A = ((b+c)*d)-h;
// Assegnamento a variabile
base
// Somma
// Sottrazione
// Prodotto
// Divisione
// Resto della divisione intera
// Cambio di segno
// Parentesi (solo tonde!)
C. Rocchini - C++
37
Riepilogo operatori
// Confronti e operatori logici
if( A==B )..
// Uguale
A != B
// Diverso
A < B
// Minore
A > B
// Maggiore
A <= B
// Minore o uguale
A >= B
// Maggiore o uguale
&&
||
!
// And (e) logico
// Or (o) logico
// Not (non) logico
// es. if( a<min || a>max) …
C. Rocchini - C++
38
Riepilogo operatori
// Incrementi e decrementi
int a = 2, b=7;
++a;
// Incremento: a vale 3
--b;
// Decremento: b vale 6
int
int
int
int
int
x
y
z
h
k
=
=
=
=
=
10;
x++;
++x;
42;
h--;
// Postincremento, x=11 ma y=10
// Preincremento, z=12 e x = 12
// Postdecremento, h=41 ma k=42
// Utilizzabile sugli interi, non su virgola mobile
C. Rocchini - C++
39
Operatori sui bit
A
A
A
A
A
A
= b & c;
= b | c;
= b ^ c;
= ~b;
= b<<3;
= b>>4;
// Esempi
(b>>2)&1
b|(1<<4)
b&~(1<<4)
(b>>8)&0xFF
//
//
//
//
//
//
And bit a bit
Or bit a bit
Xor = or esclusivo, 1 se b!=c
Not logico
Shift a sinistra (di 3)
Shift a destra
//
//
//
//
Estrazione del terzo bit
Forza a uno il quarto bit
Forza a zero il quarto bit
Parte alta di una word
<<2
1 0 1 0 1 1 1 0
1 0 1 1 1 0
C. Rocchini - C++
0 0
40
Modificatori e Exp Condizionale
// Modificatori
A += b;
// Scrittura riassuntiva di A = A + b;
A -= b;
A *= b;
…
A <<= 3;
// Equivale a A = A << 3;
// Espressione condizionale
// condizione ? valore_se_vero : valore_se_falso
A = b==0 ? 1 : 100/b;
// se b vale 0 a prende 1 altrimenti prende 100/b
// Corrisponde al se(;;) di Excel
C. Rocchini - C++
41
Ordine di valutazione
A = 3+2*3;
Record * p;
*p.valore
(*p).valore
// 9, non 15! (Anche in Basic)
// Contenuto di valore
// Contenuto di p
if( a&b==0 )
if( (a&b)==0 )
// == associa prima di &: errato!
// Corretto
// Nel dubbio usare le parentesi!
// Controllare la precedenza sul manuale
C. Rocchini - C++
42
Memoria dinamica: new, delete
int *p = 0;
*p = 7;
p = new int;
*p = 7;
delete p;
*p = 7;
//
//
//
//
//
//
Puntatore nullo
Errato: non esiste la locazione
Allocazione di un intero
Corretto
Obbligatorio dopo l’utilizzo!
Di nuovo errato
double * v = 0;
v = new double[1024];
// Allocazione di un vettore
v[907] = 3.14;
// OK: memoria allocata
…
delete[] v;
// Disallocazione: notare le []
C. Rocchini - C++
43
Cast: Conversioni di tipo
int a = 3; double x = a;
a = int(x);
// Automatica
// Cast (troncamento)
int * q;
char * p = (char *)q;
void * k;
bool * b = (bool *)k;
// Conversione di puntatore
// Puntatore “generico”
char c = char(3.14);
// Da double a char
C. Rocchini - C++
44
Istruzione condizionale
if (a>b)
c = a;
// Parentesi () obbligatorie!!
// Spaziatura non significativa!
if (a!=b)
{
c = a;
b = a;
}
// Blocco di istruzioni
if (a>b) c = a;
else
c = b;
// Utilizzo di else
C. Rocchini - C++
45
Case
switch(a)
// A seconda del valore di a
{
case 1:
// case + valore
// se a=1
break;
// Fine case
case 2:
// Doppio valore
case 3:
// se a=2 oppure 3
break;
default:
// Caso di default(case else)
// Altrimenti…
}
C. Rocchini - C++
46
Cicli while
while( a>b )
{
--a;
}
// Ciclo while
// Controllo all’inizio
do
{
// Ciclo do-while
// Controllo alla fine
--a;
} while( a>b );
C. Rocchini - C++
47
Ciclo For
// for(inizializzazione;condizione;iterazione) {}
for(a=1;a<=10;++a)
// Ciclo classico
{
// …
}
for(a=1; a<=100 ;a+=10)
// step di 10
for(a=1024; a>1; a/=2)
// Ciclo logaritmico
//Struttura scansione di un file:
//for(apri_file;not eof;leggi_carattere)
// TODO FARE ESEMPIO
C. Rocchini - C++
48
Esempio for su file
FILE * fp;
char c;
for(fp=fopen(file);!EOF(fp);c=fgetc(fp))
{
usa il carattare c
}
C. Rocchini - C++
49
goto
//Il comando goto si articola in due parti:
//Dichiarazione di una etichetta
// Comando goto per saltarci.
//Si usa raramente: in caso di errore per saltare
//Fuori da una procedure (bisognerebbe usare le
// Eccezioni
//…
goto etichetta;
//..
etichetta:
//…
C. Rocchini - C++
50
7- Funzioni
C. Rocchini - C++
51
Funzioni: Introduzione
// tipo_ritorno nome_funzione ( parametri … );
double sqrt( double x );
double sqrt( double );
// Dichiaraz. di prototipo
// Altra dichiarazione
double z = sqrt(2);
// Utilizzo (“chiamata”)
double y = sqrt(“pippo”); // Errore di tipo
// Definizione di una funzione
double doppio( double x ) // Intestazione
{
// Inizio blocco
return x*2;
// Valore “ritornato”
}
// Fine blocco
C. Rocchini - C++
52
Confronto C++ - Basic
// C++
double prodotto( int x, int y )
{
return x*y;
}
‘Basic
Function prodotto(ByVal x,y As Integer) As Double
prodotto = x * y
End Function
C. Rocchini - C++
53
Procedure e Riferimenti
void scambia( int & a, int & b ) // void = sub
{
int t = a;
a = b;
b = t;
}
// & = byreference
‘In basic
Sub scambia(ByRef a, b As Integer)
Dim t As Integer
t = a
a = b
b = t
End Sub
C. Rocchini - C++
54
Utilizzo di return nelle procedure
// il comando return senza valore puo’ essere
// utilizzato per uscire subito da una procedura
void procedura()
{
//…
if(voglio_terminare) return;
// Esco subito
// …
// Fine “naturale della procedura”
}
C. Rocchini - C++
55
“Inline” e ricorsione
// inline = consiglio al compilatore, per funzioni
// piccole e semplici: programma piu’ veloce
inline int fattoriale( int n )
{
return n<2 ? 1 : n*fattoriale(n-1);
}
long fibonacci( long n )
{
return n<3 ? 1 : fibonacci(n-1)*fibonacci(n-2);
}
C. Rocchini - C++
56
Variabili statiche
void proc( int x )
{
int a = 0;
// Semplice variabile locale
a += x;
// Ricreata ad ogni chiamata
printf(“%d\n”,a);
}
void proc( int x )
{
static int a = 0; // Variabile statica “persistente”
a += x;
// Memorizza la somma degli x
printf(“%d\n”,a);
}
C. Rocchini - C++
57
Variabili Statiche: Caso concreto
// Procedura che necessita di una inizializzazione
// complessa dei dati (da fare una volta sola):
void operazione( char c )
{
static bool prima_chiamata = true;
if(prima_chiamata)
{
// … Inizializzazione …
prima_chiamata = false;
}
// … operazione su c …
}
C. Rocchini - C++
58
Argomenti vettore
// I vettori sono sempre passati by reference
// Non possono essere valori di ritorno di funzioni
int modifica( double v[1000] )
{
v[3] = 7;
// modifico il vettore passato
}
// Non e’ obbligatorio specificare la dimensione
int modi( double v[] )…
double v1[32]; double v2[1024]; modi(v1); modi(v2);
// Per le matrici e’ obbligatorio specificare solo
// la seconda dimensione
double determinante( double M[][16] )…
C. Rocchini - C++
59
Sovraccarico di nomi
// E’ possibile dare lo stesso nome a varie funzioni
void stampa( int x )
// Funzione stampa
{
printf(“%d\n”,x);
}
void stampa( double x )
// Un’altra funzione stampa
{
printf(“%g\n”,x);
}
int k = 3; stampa(k);
// Chiama la prima funzione
double h = 3.9; stampa(h); // Chiama la seconda
C. Rocchini - C++
60
Sovraccarico: ambiguità
int
f( int x )
double f( int x )
int k = 9; f(k);
{ return x*2; }
{ return x*3; }
// Errore: ambiguo!
// Le funzioni sono distinte dai parametri ma non
// dal tipo di ritorno!
C. Rocchini - C++
61
Argomenti di default
// E’ possibile specificare i valori di default
// degli argomenti di una fuzione
void stampa( char * str, int dimensione = 16)
{
// …
}
stampa(“pippo”,4);
Stampa(“pluto”);
// Ok: dimensione = 4
// OK: dimensione = 16
void f( int a = 3, int b ) // Errore!
// Si puo’ specificare solo gli ultimi valori!
C. Rocchini - C++
62
Argomenti Costanti
// Sara’ importantissimo nei membri di classe
// Scrivetelo tutte le volte che e’ possibile
void funzione ( const int a )
{
int b = a;
// OK: lettura valore
a += 3;
// Errore: modifca di a
}
// Il passaggio per valore copia i dati
void stampa_stringa( std::string str ) …
// Il reference evita la copia dei dati
// Il const impedisce modifiche erronee
void stampa_stringa( const std::string & str ) …
C. Rocchini - C++
63
7b – Il Preprocessore
C. Rocchini - C++
64
Inclusione di file
//
//
//
//
Il preprocessore e’ un programma a parte
Esegue modifiche sul testo tramite semplici
comandi prima che il file sia compilato
Le istruzione del prep. Iniziano sempre con #
// Il comando #include copia un file testo nel
// punto indicato
#include <stdio.h>
#include “mio.h”
// Inclusione di file di libreria
// Inclusione di file locale
C. Rocchini - C++
65
Macro
// Il comando #define esegue una riscrittura
#define K 12345
a+K
a+12456
// Puo’ avere parametri
#define somma(x,y) x+y
somma(3,4)
3+4
somma(3,5)*6
3+5*6
#define PI 3.1415926
// ma e’ meglio: in questo caso ha un tipo
const double PI = 3.1415926;
#undef PI
// Cancella la definizione
#define VALORE
// Definito a vuoto ma valido
C. Rocchini - C++
66
Compilazione condizionale
// Il comando #ifdef permette di considerare o no
// alcune parti di testo. Esiste anche #ifndef
#ifdef SINGOLA_PRECISIONE
float v[32];
float x;
#else
double v[32];
double x;
#endif
x = v[7];
// Inizio IF
// Else
// Fine IF
// float o double
C. Rocchini - C++
67
Compilazione Cond: caso tipico
// Trucco per includere una sola volta l’header
// di una libreria:
#ifndef __MIA__LIBRERIA__
#define __MIA__LIBRERIA__
int mia_funzione( int x );
//… codice header
#endif
C. Rocchini - C++
68
8 - Namespace
C. Rocchini - C++
69
Introduzione
// I namespace permettono di rendere modulare il
// codice definendo delle librerie:
namespace mia_lib
// Inizio libreria
{
int var = 5;
// Def. Di variabile
int fun( int x );
// Definizione di funzione
}
// Fine libreria
var = 6;
// Errore: variabile non definita!
mia_lib::var = 6;
// OK
mia_lib::fun(5);
// Nota: in basic al posto di :: si usa il punto
C. Rocchini - C++
70
Namespace: continua
//
//
using
var =
Using permette di omettere il nome della libreria
(Simile al with sui record del basic
namespace mia_lib;
6;
// OK: var e’ nella libreria mia_lib
// std e’ la libreria standard del C++
std::string s;
// string fa parte di std
using namespace std;
string s2;
// OK: utilizzo la libreria std
C. Rocchini - C++
71
X1 - Una libreria: stdio
C. Rocchini - C++
72
Librerie
Il c/c++ interagisce con il mondo tramite librerie.
Se si vuole leggere la tastiera, aprire una finestra,
leggere e scrivere un file, suonare, utilizzare la
rete o i database, si devono utilizzare librerie
aggiuntive. Le librerie sono decime di migliaia. Le
librerie sono formate da funzioni e strutture dati.
Ne vedremo una per l’utilizzo di file:
Ci sono anche
io-> a bassissimo livello
streams-> ad altissimo livello
C. Rocchini - C++
stdio.
73
Lettura Binaria
#include <stdio.h> // Inclusione header di stdio
int main()
{
FILE * fp;
// Descrittore di file (solo *!)
// Apertura in lettura di un file
fp = fopen(“c:/temp/prova.txt”,”rb”);
MioDato d[3];
// Lettura binaria di un dato
int r = fread(d,3,sizeof(MioDato),fp);
if(r==0)
… END OF FILE…
fclose(fp);
// Chiusura file
return 0;
}
C. Rocchini - C++
74
Scrittura Binaria
#include <stdio.h> // Inclusione header di stdio
int main()
{
FILE * fp;
// Descrittore di file (solo *!)
// Apertura in scrittura di un file
fp = fopen(“c:/temp/prova.txt”,”wb”);
if(fp==0) … errore…
double v;
// Scrittura binaria di un dato (Nota la &)
fwrite(&d,1,sizeof(MioDato),fp);
fclose(fp);
// Chiusura file
return 0;
}
C. Rocchini - C++
75
Scrittura testuale
FILE * fp = fopen(“prova.txt”,”w”);
fputc(‘c’,fp);
// Scrittura di un carattere
fputs(“cavallo”,fp);
// Scrittura di stringa
fputc(‘\n’,fp);
// Ritorno a capo
// Esempi di scrittura formatta
// Vedere il manuale!
fprintf(fp,”%d %g”,3,9.7);
fprintf(fp,”%s %30.20f”,stringa,valore_num);
fprintf(fp,”%X \n”,numero_ex);
fclose(fp);
C. Rocchini - C++
76
Lettura testuale
FILE * fp = fopen(“prova.txt”,”w”);
int c = fgetc(‘c’,fp);
// Lettura di un carattere
if(c==EOF) … END OF FILE…
char buf[MAX];
fgets(buf,MAX,fp);
// Lettura di una riga!
// Esempi di Lettura formatta
// Notare la &: parametri puntatore!
fscanf(fp,”%d %g”,&v1,&v2);
fscanf(fp,”%30.20f”,&valore_num);
fscanf(fp,”%X”,&numero_ex);
fclose(fp);
C. Rocchini - C++
77
Accesso Libero (Random)
// Posizione corrente nel file (in byte!)
long l = ftell(fp);
// Spostamento al 42esimo byte del file
fseek(fp,SEEK_SET,42);
// Avanzamento di 80 byte
fseek(fp,SEEK_CUR,80);
// Spostamento al 42esimo byte della FINE del file
fseek(fp,SEEK_END,42);
C. Rocchini - C++
78
Input/output
// Nella applicazioni console, esistono sempre due
// file automaticamente aperti:
//
stdin in lettura = tastiera
//
stdout in scrittura = schermo
// (In realta’ sono 3: esiste anche stderr…)
fprintf(stdout,”Buongiorno\n”);
int c = fgetc(stdin);
// Legge da tastiera
// Per ogni funzione esiste la versione compatta
// senza file parametro e senza f nel nome:
printf(“Buongiorno\n”);
// su stdout
int c = getc();
// da stdin
scanf(“%d”,&x);
// Legge da stdin
C. Rocchini - C++
79
Stdio: Per finire
// scanf e printf esistono in versione stringa:
char buf[1024];
sprintf(buf,”numeri: %g %d\n”, 3.5, 9 );
…
sscanf(buf,”%x%s”,…);
// La scrittura su disco e’ spesso bufferizzata
// (vale a dire ritardata) per motivi di efficienza
// fflush costringe il sistema ad effettuare
// immediatamente una scrittura fisica:
fflush(fp);
C. Rocchini - C++
80
5 – Puntatori e Vettori
C. Rocchini - C++
81
I puntatori
La variabili sono allocate in memoria, le zone di memoria sono
indirizzabili da indirizzi numerici. I Puntatori sono
indirizzi di memoria. (* = puntatore) ( & = indirizzo )
std::string pippo = “Claudio”;
std::string * ptr = &pippo;
pippo:
“Claudio”
ptr: Indirizzo di pippo
C. Rocchini - C++
82
Puntatore nullo ed Esempi
// Il puntatore nullo e’ rappresentato dal valore 0
// Corrisponde al nothing del Basic
char * p = 0; // Valore nullo
int * p;
int **q;
int * v[32];
// Puntatore ad un intero
// Puntatore ad un puntatore ad un intero
// Vettore di 32 puntatori ad intero
void * z;
// Puntatore senza tipo
z = p;
p = z;
P = (int *)z;
// OK: da tipo a senza tipo
// Errore: specifica di tipo!
// OK: conversione esplicita di tipo
C. Rocchini - C++
83
Inizializzazione di vettori
// E’ possibile inizializzare i vettori direttamente
int v[4] = {3,91,23,4};
char k[3] = { ‘a’,’b’,’c’ };
double m[2][2] =
{
{1,2},
{3,4}
};
int w[] = {3,6,7,8};
// Lunghezza implicita
C. Rocchini - C++
84
Puntatori e vettori
int v[20];
int * p = v;
// Il nome di un vettore e’ il puntatore al
// Primo elemento
int * w = v+7; // Puntatore all’ottavo elemento (0=primo)
// Scorrimento di un vettore con indice intero
int i;
for(i=0;i<20;++i)
printf(“%d “,v[i]);
// Scorrimento di un vettore con puntatore (piu’ veloce!)
int * j;
for(j=v;j<v+20;++j)
printf(“%d “,*j);
// *j = contenuto di j
C. Rocchini - C++
85
9 – Sorgenti e programmi
C. Rocchini - C++
86
Moduli
• Un programma di medie dimensioni non e’ mai
scritto in un unico sorgente .c++
• I programmi sono suddivisi in moduli, cioe’ in
file separati.
• La separazione dipende dalla logica del
programma (oggetti separati in file separati).
• E’ possibile compilare separatamente i vari
moduli.
• Le modifiche di un modulo in genere non
interferiscono con gli altri.
• Gruppi di moduli comuni sono raccolti in
librerie.
C. Rocchini - C++
87
Header e Sorgenti
• Ad un modulo (file .c++) che
esporta simboli e’ associato un
file di intestazione (header .h)
• L’header contiene la specifica dei
simboli esportati.
• Le librerie standard
(stdio,vector,stdlib) sono formati
da moduli in forma di librerie +
header da includere con il comando
#include
C. Rocchini - C++
88
Variabili e funzioni locali
// Di default, variabili e funzioni vengono
// esportate dal modulo.
int pippo; // Variabile esportata
void mia_funzione( int x )
// Funz. esportata
{
…
}
// Gli oggetti dichiarati static invece non
// vengono esportati
static int pluto; // Privata del modulo
static void altra_funzione( int x ); // Privata
C. Rocchini - C++
89
Creazione dell’header
// File mio.c++
// File mio.h
//Per essere utilizzati,
//i simboli esportati
//devono essere dichiarati
//nell’header
int pippo;
void funzione( int x )
{
…
}
//Per distinguerla da una
//dichiarazione, la def.
//della variabile deve
//essere preceduta da
//extern.
extern int pippo;
//Per le funzioni si
//scrive il “prototipo”
void funzione( int x );
C. Rocchini - C++
90
Schema di utilizzo
// file: mio.h
void funzione(int x);
// file: main.c++
// Inclusione header
#include “mio.h”
// file: mio.c++
void main()
{
// Utilizzo delle funz.
funzione(3);
}
static int y = 42;
void funzione(int x)
{
printf(“%d”,x+y);
}
C. Rocchini - C++
91
Cosa si mette nell’header?
// Define
#define PI 3.1415296
// Prototipi di funzione esportate
void funzione(int x);
// Def. Variabili esportate
extern bool pippo;
// Implementazioni di funzioni inline!!!!
inline int minimo(int x, int y)
{
return x<y ? x : y;
}
C. Rocchini - C++
92
Protezione dalla doppia
inclusione
// Di solito includere due volte un header comporta
// un errore; di solito di protegge gli header dalla
// doppia inclusione nel seguente modo
#ifndef __COSTANTE_DAL_NOME_VERAMENTE_STRANO__
#define __COSTANTE_DAL_NOME_VERAMENTE_STRANO__
// Corpo dell’header
// …
#endif
C. Rocchini - C++
93
10 – Classi !!!!!
C. Rocchini - C++
94
Introduzione alle classi
•
•
•
•
•
Le classi sono il vero cuore del C++
Permettono di utilizzare e definire oggetti
Una classe definisce un nuovo tipo
Una classe contiene dati e funzioni
Ci sara’ molto altro da dire…
C. Rocchini - C++
95
Utilizzo di una Classe (Oggetto)
// std::string e’ un oggetto, non ha attributi,
// ha solo membri.
std::string str;
// Dichiarazione di oggetto
str = “Claudio”;
// Assegnazione valore
printf(“%u\n”, str.length() );
str = str + “ Rocchini”;
// Chiamata membro
// Espressione
std::string x = str.substr(0,4); // Sottostringa
C. Rocchini - C++
96
Esempio in C : data
struct Data
// Dati
{
int giorno,mese,anno;
};
// Procedure
void inizializza_data( data & d, int g, int m ,int a )
{
data.giorno = g;
data.mese
= m;
data.anno
= a;
}
// Utilizzo
Data k; inizializza_data(k,28,6,1967);
C. Rocchini - C++
97
Esempio in C (continua)
void aggiungi_anni( Data & d, int anni )
{
d.anno += anni;
}
// Notare il riferimento costante:
// Evita la copia
void stampa_data( const Data & d )
{
printf(“%02d/%02d/%d\n”, d.giorno, d.mese, d.anno);
}
…
C. Rocchini - C++
98
Stesso Esempio in C++
// All’inizio la definizione di classe sembra
// una struttura
class Data
{
int giorno,mese,anno;
};
Data d;
// Dichiarazione di variabile
C. Rocchini - C++
99
Esempio (2): funzioni membro
class Data
// Dichiarazione di classe
{
int giorno,mese,anno;
// Dati
void aggiungi_anni( int anni );
// Membro
};
// Definizione classe membro
void data::aggiungi_anni( int anni )
{
anno += anni;
}
Data d; d.aggiungi_anni(3);
C. Rocchini - C++
// Chiamata del membro
100
Esempio (2): funzioni membro
class Data
// Dichiarazione di classe
{
int giorno,mese,anno;
// Dati
void aggiungi_anni( int anni );
// Membro
};
// Definizione classe membro
void data::aggiungi_anni( int anni )
{
Specifica di classe
anno += anni;
}
Riferimento all’attributo
Data d; d.aggiungi_anni(3);
C. Rocchini - C++
// Chiamata del membro
101
Funzioni membro: string
namespace std
{
class string
{
int length();
…
};
}
// Inizio namespace
// Inizio classe stringa
// Funzione membro
// Fine classe
// Fine namespace
std::string str;
int lunghezza = str.length();
C. Rocchini - C++
// Chiamata di membro
102
Controllo di Accesso
class Data
{
private:
int giorno,mese anno;
int mia_funzione();
public:
void stampa();
};
Data d;
d.giorno = 3;
d.mia_funzione();
d.stampa();
// Dati e membri privati
// Dati e membri pubblici
// Errore: dato privato
// Errore: membro privato
// OK: membro pubblico
C. Rocchini - C++
103
Accesso e Membri
class Data
{
private:
int giorno,mese anno;
public:
void stampa();
};
void Data::stampa()
{
printf(“%d\n”,giorno);
}
// Dati e membri privati
// Dati e membri pubblici
// Def. della procedura
// OK: un membro puo’ sempre
// accedere ai dati della
// sua classe!
C. Rocchini - C++
104
Incapsulamento
class pippo
{
..dati
// Dati privati: default = privato
public:
// Zona pubblica
void interfaccia1();
void interfaccia2();
};
// La protezione dell’implementazione e’ una delle
// basi dell’incapsulamento: nascondere
// l’implementazione permette di cambiarla in seguito.
// Nota: esiste anche protected, lo vedremo in seguito
C. Rocchini - C++
105
Costruttore
// Il costruttore e’ una procedura chiamata
// automaricamente alla creazione di un oggetto
class Data
{
int giorno, mese, anno;
public:
Data();
// Dichiarazione costruttore
};
Data::Data()
// Codice costruttore (non ha tipo)
{ giorno = 1;
}
Data d;
// Chiama il costruttore (giorno=1)
C. Rocchini - C++
106
Costruttore con Parametri
class Data
{
int giorno,mese,anno;
// Costruttori
public:
Data();
// Default
Data( int g, int m, int a );
// Con parametri
};
Data::Data() {}
// Def. default
Data::Data(int g, int m, int a)
// Def. Con parametri
{
giorno=g; mese=m; anno=a;
}
Data d1;
// Chiama il primo costruttore
Data d2(28,6,1967);
// Chiama il secondo costruttore
C. Rocchini - C++
107
Distruttore
// Il distruttore viene chiamato quando l’oggetto e’ distrutto
class Oggetto
{
public:
Oggetto();
// Costruttore
~Oggetto();
// Distruttore
};
Oggetto:: Oggetto() { printf(“Creazione\n”); }
// Dichi.
Oggetto::~Oggetto() { printf(“Distruzione\n”); }
// Dichi.
if(true)
{
Oggetto x;
}
// L’oggetto e’ creato
// Fine blocco: l’oggetto e’ distrutto
C. Rocchini - C++
108
Costruttore e distruttore
class MioFile
{
public:
FILE * fp;
MioFile();
~MioFile();
};
MioFile::MioFile() { fp = 0; }
// Inizializzo a null
// Chiusura automatica del file
MioFile::~MioFile() { if(fp) fclose(fp); }
MioFile f; f.fp = fopen(…);
C. Rocchini - C++
// Chiusura aut.
109
Dati di Classe Statici
// I dati statici di classe sono UNICI per tutti gli
// oggetti di quella classe
class Oggetto
{
public:
static int numero_oggetti; // Unico per tutta la classe
Oggetto();
// Costruttore
};
// I dati di classe statici devono essere definiti:
Oggetto::numero_oggetti = 0;
Oggetto::Oggetto() { ++ numero_oggetti; } //Def. Costruttore
Oggetto o1;
printf(“%d\n”,o1.numero_oggetti);
Oggetto o2,o3; printf(“%d\n”,o1.numero_oggetti);
C. Rocchini - C++
// -> 1
// -> 3
110
Funzioni Membro statiche
// Le funzioni membro statiche non fanno riferimento ai
// dati della classe (oppure solo ai dati statici).
class Data
{
public:
static std::string nome_classe(); // Membro statico
}
std::string Data::nome_classe()
{ return “CLASSE DATA”;
}
// Def. Membro statico
Data d; printf(“%s\n”,d.nome_classe());
printf(“%s\n”, Data::nome_classe() );
C. Rocchini - C++
// Call oggetto
// Call diretta
111
Funzioni Membro Costanti
// I membri che non modificano i dati dell’oggetto devono
// essere dichiarati costanti.
class Data
{
int giorno,mese,anno;
public:
bool bisestile() const;
// Membro costante
}
bool Data::bisestile() const // Definizione
{
return anno%4==0 && anno%100!=0;
// Non modifica i dati
// ++anno -> errore: modifica i dati
}
C. Rocchini - C++
112
Autoriferimento
// this e’ il puntatore all’oggetto corrente (me in VB)
class NodoLista
{
public: NodoLista * successore;
public: void link( NodoLista & n );
};
// Implementazione di link
void NodoLista ::link( NodoLista & n )
{
n.successore = this;
}
C. Rocchini - C++
113
Utilizzo dell’Autoriferimento
// Spesso e’ utile che un membro ritorni un
// Riferiemtno all’oggetto
Data & Data::incrementa_giorno()
{
++giorno;
// Incrementa il giorno
return *this;
// Ritorna il rif. a se stesso
}
Data d;
// Chiamata in “cascata” dei membri
d. incrementa_giorno().stampa();
C. Rocchini - C++
114
Definizioni Interne alla classe
// Scrittura classica
class Data
{
int g;
public:
int & giorno();
};
// Scrittura Compatta
class Data
{
int g;
public:
int & giorno()
{
return g;
}
};
C. Rocchini - C++
115
Direttiva inline
//
//
//
//
La direttiva inline deve essere usata per funzioni
semplici: modifica la tecnica di chiamata di
Procedura. Non puo’ essere usata per funzioni
Complesse
inline int & Data::giorno()
{
return g;
}
// E’ una specifica di bassisimo livello come lo
// era register. Forse verra’ eliminata
C. Rocchini - C++
116
Sovraccarico degli Operatori
// Si possono ridefinire gli operatori come funzioni
// operator== e’ il nome della funzione
inline bool operator== ( const Data & d1, const Data & d2 )
{
return d1.g==d2.g && d1.m==d2.m && d1.a==d2.a;
}
inline bool operator!= ( const Data & d1, const Data & d2 )
{
return d1.g!=d2.g || d1.m!=d2.m || d1.a!=d2.a;
}
if( data1 == data2 )…
// Chiama la nostra funzione
C. Rocchini - C++
117
Sovraccarico dei membri
class Data
{
public:
int g,m,a;
Data & operator+= ( int ng );
};
// Implementazione del membro
Data & Data::operator+= ( int ng )
{ g += ng;
// Modifica giorni
return *this;
// Ritorna il rif. a se stesso
}
Data d(3,12,2004); (d += 3).print();
// 6/12/2004
C. Rocchini - C++
118
Esempio concreto: un file come
vettore di caratteri
class VFile
{
private:
FILE * fp;
public:
VFile() { fp = 0; } // Definizione abbreviata del costr.
~VFile() { if(fp) fclose(fp); }
// Chiusura autom.
bool open(char * name ) { return ( fp=fopen(name,”r”) ); }
char operator[] ( int p )
// Op []!
{
fseek(fp,SEEK_SET,p);
return fgetc(fp);
}
};
VFile ff; ff.open(“prova”); int x = ff[31];
C. Rocchini - C++
119
Operatore in scrittura?
class FileReference {
private: long pos; FILE * fp;
FileReference( long p, FILE * f ) { pos=p; fp=f;}
FileReference & operator= ( char c )
{
fseek(fp,SEEK_SET,pos);
fwrite(&c,1,1,fp);
return *this;
}
};
FileReference Vfile::operator[] ( long i ){
return FileReference(i,fp);
}
vf[42] = 5;
C. Rocchini - C++
120
Operatore di Assegnamento
// Ne viene creato uno di default che copia i dati
// Ma e’ anche possibil riscrivero
class Data
{ …
Data & operator= ( const Data & d );
};
// Implementazione
Data & Data::operator= ( const Data & d )
{
g = d.g; m = d.m; a = d.a;
return *this;
}
Data d1,d2,d3;
d1 = d2 = d3;
C. Rocchini - C++
121
Oggetti membro
class Evento
{
public:
Data d;
std::string nome;
// Costruttore con parametri di membri oggetto
Evento( std::string n, int g, int m, int a ):d(g,m,a)
{
nome = n;
}
};
Evento e(“nascita”,28,6,1967);
C. Rocchini - C++
122
11 – Sovraccarico degli operatori
C. Rocchini - C++
123
Introduzione
Gli operatori simbolici operanti sugli oggetti possono essere
ridefiniti. Questo vuol dire che posso chiamare una funzione
con un simbolo di operatore.
C. Rocchini - C++
124
Esempio: data ++
class data {
public:
int g,m,a;
void operator++ () {
if(++g==ultimo_giorno[m]){
g = 1;
if(++m>12){
m = 1;
++a;
}
}
}
};
Data d; ++d;
// Chiama la funzione operator
C. Rocchini - C++
125
Esempio: confronto di date
class Data {
…
// Operatore costante con parametro costante
bool operator< ( const Data & d ) const
{
if(a!=d.a) return a<d.a;
if(m!=d.m) return d<d.m;
return g<d.g;
}
};
Data d1,d2;
…
if( d1<d2 )…
// Utilizzo dell’operatore <
if( d1>d2 ).. // Errore! > non definito (neanche di default)
C. Rocchini - C++
126
Una semplice classe: Point2
// Definiremo la classe punto (o vettore bidimensionale)
class Point2
{
private:
double v[2];
public:
//… membri …
};
// Intestazione
// Dati privati
// Dati della classe: x,y
// Membri pubblici
// Notare il ‘;’
C. Rocchini - C++
127
Costruttori (Niente distruttore)
inline Point2()
// Costruttore di default
{
// Niente da fare (ma obbligatorio dichiarare la funzione)
}
inline Point2( double v0, double v1 )
{
v[0] = v0;
// Costruttore con
v[1] = v1;
// Inizializzazione
}
I costruttori sono chiamati automaticamente quando l’oggetto
viene creato.
C. Rocchini - C++
128
Operatore di assegnamento
inline Point2 & operator= ( const Point2 & p )
{
v[0] = p.v[0];
// Copio x
v[1] = p.v[1];
// Copio y
return *this;
}
Note: la stringa ‘operator=‘ è il nome della funzione.
Mentre Point2 & e’ il tipo di ritorno. Il parametro e’
costante riferimento per evitare la copia.
Il tipo del parametro è obbligatorio, come il valore di
ritorno che permette di concatenare le espressioni: a
= b = 3; infatti a = (ritorno di b=3);
C. Rocchini - C++
129
Metodo somma
inline Point2 operator+ (const Point2 & p) const
{
return Point2( v[0]+p.v[0], v[1]+p.v[1] );
}
Note: il primo operando dell’operatore somma è
l’oggetto in questione (this). L’operatore è const
(non modifica l’oggetto). Si utilizza il costruttore
con parametri per costruire “al volo” il valore di
ritorno. Il parametro p è passato per riferimento per
motivi di efficienza.
Il membro e’ costante: non modifica l’oggetto
C. Rocchini - C++
130
Funzione di stampa
inline void show() const
{
printf(“[%g,%g]\n”,v[0],v[1]);
}
Metodo per la visualizzazione della classe; l’oggetto è
visualizzato nella forma: [v0,v1].
C. Rocchini - C++
131
Esempio di utilizzo
int main()
{
Point2 a(2,4);
Point2 b(3,2);
Point2 c;
c = a+b;
c.show();
return 0;
}
// Costr. con iniziliz.
// Costruttore default
// Somma ed assegnamento
// Visualizzazione
// Risultato: [5,6]
C. Rocchini - C++
132
Membri di accesso ai dati
// Versione costante
inline const double & x() const { return v[0]; }
inline const double & y() const { return v[1]; }
// Versione non costante
inline double & x() { return v[0]; }
inline double & y() { return v[1]; }
Point2 p1,p2;
p1.v[0];
//
K = p1.x(); //
p2.x() = 3; //
K = (p1+2).x();
Errore dato privato
OK: accesso costante
OK: accesso non costante
// OK: accesso costante a temporaneo
C. Rocchini - C++
133
Membri modificatori
inline Point2 & operator+= ( Point2 const & p )
{
v[0] += p.v[0];
v[1] += p.v[1];
return *this;
}
Nota: il membro non e’ costante, ritorna il riferimento
a se stesso per operazioni in cascata, tipo:
a = ( b+=c );
C. Rocchini - C++
134
Ordinamento
inline bool operator==
{
return v[0]==p.v[0]
}
inline bool operator!=
{
return v[0]!=p.v[0]
}
inline bool operator<
{
return v[1]!=p.v[1]
}
( const Point2& p ) const
&& v[1]==p.v[1];
( const Point2& p ) const
|| v[1]!=p.v[1];
( const Point2& p ) const
? (v[1]<p.v[1]) : (v[0]<p.v[0]);
C. Rocchini - C++
135
Oggetti Funtori
// Ridefinendo l’operatore chiamata di funzione
// (), e’ possibile creare oggetti che si
// comportano come funzioni.
class Doppiatore
{
public:
double operator() ( double x ) { return x*2; }
};
Doppiatore d;
printf(“%g”, d(7) );
// Stampa 14
C. Rocchini - C++
136
12 – Classi derivate
C. Rocchini - C++
137
Derivazione
// E’ possibile derivare una classe da un’altra
// La nuova classe eredita tutti gli attributi
class Point2 { public: double v[2]; };
class Punto_Colorato : public Point2
{
public:
Colore c;
};
Punto_Colorato k;
k.c = rosso;
k.v[0] = 3;
// Attributo della nuova classe
// Eredita i metodo di Point2
C. Rocchini - C++
138
Sovrascrittura di membri
class Point2 { … void stampa(); }
class Punto_Colorato : public Point2
{
…
void stampa();
// Riscrive la funzione di Point2
};
Punto_Colorato p; p.stampa(); // Chiama la riscritta
void Punto_Colorato::stampa() // Implementazione
{
stampa_colore(c);
Point2::stampa();
// Invocazione funzione originale
}
C. Rocchini - C++
139
Puntatori a classi derivati
// I puntatori a classi derivate sono interscambiabili
Punto_Colorato pc;
double
k;
Point2 * punt = &pc; // OK: classe padre
Point2 * pun2 = &k; // Errore: double non deriva da P2
// I metodo da chiamare sono derivati dal tipo
punt->stampa();
// Chiama il metodo di Point2 anche se l’oggetto e’
// un Punto_Colorato (non stampa il colore)
pc.stampa(); // Stampa il colore
C. Rocchini - C++
140
Gerarchie di Classi ed Interfacce
Le gerarchie di classi sono fondamentali nelle interfacce.
• OggettoGenerico
– Finestra (.disegna)
• Controllo (.disegna, .evento)
– Bottone (.evento)
» BottoneRadio (.selezionato)
» BottoneCheck (.stato)
» BottoneComando (.evento)
– Lista
– CampoTesto (.valore)
• FinestraCornice
– DocumentoSingolo
– MultiDocumento
C. Rocchini - C++
141
Gerarchie esempio MFC
C. Rocchini - C++
142
Metodi virtuali
// Per fare in modo che il metodo non dipenda dal tipo
// ma dall’oggetto nell’uso di puntatori si usa:
class Point2
{
public:
virtual stampa();
};
Punto_Colorato pc;
Point2 * punt = &pc;
punt->stampa();
// Chiama Punto_Colorato perche’ virtual
C. Rocchini - C++
143
Note a Virtual
Nel Basic tutti i metodo sono virtual.
Nel c++ si e’ deciso di rendere virtual alcuni
metodo esplicitamente, perché questo rende leggermente
più lento il programma: infatti questo è l’unico caso
che comporta un controllo di tipo durante l’esecuzione
del programma.
D’altro canto il meccanismo è indispensabile,
soprattutto nelle interfacce grafiche.
C. Rocchini - C++
144
Classi astratte
// E’ possibile definire membri puramente virtuali che
// definiscono classi astratte. In Java si chiamano
// interfacce.
class PuntoAstratto
{
public:
virtual void stampa() = 0; // =0 -> virtuale pura
};
PuntoAstratto p;
// ERRORE: classe astratta
class PuntoReale
{
public:
virtual void stampa();// OK: definisce stampa in concreto
}
C. Rocchini - C++
145
13 - Template
La vera potenza del C++ !
C. Rocchini - C++
146
Introduzione ai Template 1
• Supponiamo di voler realizzare la funzione
minimo di due interi:
inline int minimo( int a, int b )
{
if(a<b) return a;
else
return b;
}
int x = minimo(7,9);
// Nota: inline perché e semplice
C. Rocchini - C++
147
Introduzione ai Template 2
• Adesso voglio il minimo fra due double:
inline double minimo( double a, double b )
{
if(a<b) return a;
else
return b;
}
Le due funzioni sono identiche a parte la def.
dei tipi. Se voglio altre funzioni minimo (short,
Stringhe, oggetti le devo scrivere tutte).
C. Rocchini - C++
148
Introduzione ai Template 3
• In C++ e’ possibile passare un tipo come parametro ad
una funzione (o ad una classe):
template<class T>
// T e’ il parametro tipo
inline T minimo( T a, T b )
{
if(a<b) return a;
else
return b;
}
// Utilizzo:
double x = minimo<double>(3.9, 7.5);
// T=double
int k = minimo<int>(4,5);
// T=int
int s = minimo(2,3); // Inferenza del tipo: T=int
C. Rocchini - C++
149
Nota Implementativa
• I template sono parametri di tipo “tipo”
• Sono realizzati con la massima efficienza
(nessun controllo al tempo di esecuzione).
• Permettono di creare classi od algoritmi
generici, non dipendenti dal tipo dei dati.
• Esempi tipici: algoritmo di ordinamento di un
vettore. Contenitori senza tipo.
• Il C++ e’ l’unico linguaggio di programmazione
che ha i template.
• I template sono la base costruttiva della
Libreria Standard.
C. Rocchini - C++
150
Classi Template
// Es. Posso definire la classe Punto senza
// Specificare il tipo delle coordinate
template<class S>
class Point2
{
public: S v[2];
};
Point2<double> p1; // Punto doppia precisione
Point2<float > p2; // Punto singola precisione
Point2<int
> p3; // Punto intero
C. Rocchini - C++
151
Esempio template!
• Es1: point
– Consultate i lucidi relativi
alla esercitazione 1: classe
point
• Es2: vector
– Consultate i lucidi relativi
alla esercitazione 2: classe
vector
C. Rocchini - C++
152
3 Libreria Standard
C. Rocchini - C++
153
Introduzione alla STL
• La libreria standard e’ uno dei punti più alti
dell’informatica.
• Raccoglie i risultati teorici dell’informatica
sugli algoritmi e le strutture dati creati nel
corso degli anni.
• Se ho bisogno di un algoritmo, e’ probabile che
ci sia gia’ scritto nella STL.
• Ogni elemento dell’STL e’ realizzato con la
massima efficienza.
C. Rocchini - C++
154
Stringhe
• Il C++ non ha il tipo stringa come oggetto
base; la libreria standard introduce l’ogggetto
string:
std::string str = “Pippo”;
int l = str.length();
// Tutta la libreria standard e’ contenuta
// nel namespace std. Ovviamente e’ possibile
// utilizzare:
using namespace std;
C. Rocchini - C++
155
STL - Contenitori
• I contenitori sono oggetti che
contengono altri oggetti.
• Ogni contenitore ha le proprie
caratteristiche.
• I contenitori comprendono: vector,
list, map, set, deque, stack, heap.
• I contenitori sono template sul tipo di
oggetto contenuto.
C. Rocchini - C++
156
STL - iteratori
• Ad ogni contenitore e’ associato il
proprio oggetto iteratore.
• L’iteratore serve per scorrere gli
elementi di un contenitore (e’ una
estensione del puntatore, vale a dire
che un iteratore “punta” ad un elemento
dentro il contenitore).
C. Rocchini - C++
157
Vector
// vector introduce i vettori dinamici non presenti nel
// C++ base.
// Vector ha un parametro template sul tipo Contenuto:
vector<int> v; v.resize(1000); v[999] = 3;
vector<Data> d;
// Vettore di date
// d.front() : primo elemento |d.begin() : it inizio
// d.back() : ultimo elemento|d.end()
: it fine
// Scansione:
vector<Data>::iterator i; // iteratore associato
for(i=d.begin();i!=d.end();++i)
i->stampa();
// si usa come un puntatore
C. Rocchini - C++
158
List
List implementa le liste di oggetti. List non ha
l’operatore [] (non e’ possibile indirizzare
l’ennesiomo elemento), ma l’inserimento e
l’estrazione di un elemento sono molto veloci.
list<double> l;
// Lista di valori
l.push_front(9);
// Inserimento in testa
l.push_back(11);
// Inserimento in coda
list<Data>::iterator i;
// iteratore associato
for(i=l.begin();i!=d.end();++i)
printf(“%g “,*i); // si usa come un puntatore
// Nota la scansione e’ identica al vettore
C. Rocchini - C++
159
Map
Map e’ un contenitore molto potente: implementa
un vettore “autoassociativo”, vale a dire un
oggetto che assomiglia ad un vettore, ma
utilizza come indice un qualsiasi altro oggetto
(E’ implementato con un B*-albero red/black).
Map e’ un template con due parametri: oggetto
indice e oggetto contenuto.
map<Data,string> eventi; // Da date a stringhe
eventi[ Data(28,6,1967) ] = “Compleanno”;
string s = eventi[Data(28,6,1967)];
C. Rocchini - C++
160
Altri contenitori
• deque e’ una coda (chi primo arriva, primo e’
servito).
• stack e’ una pila (per chi sa a cosa serve).
• heap e’ una coda con priorita’, vale a dire che
e’ una coda con qualcuno raccomandato.
• set e’ un contenitore insieme (in senso
matematico)
• Tutti hanno i propri iteratori.
C. Rocchini - C++
161
Algoritmi di ricerca
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
for_each
find
find_if
adjacent_find
find_first_of
count
count_if
mismatch
equal
search
search_n
find_end
Applica un operatore ad ogni elem.
Cerca un elemento
Cerca secondo una condizione
Prima coppia di uguale consecutivi
Cerca un elemento da un insieme
Conta gli elementi
Conta secondo una condizione
Primo elemento diverso fra due ins.
Controllo l’uguaglianza
Cerca sottosequenza
Cerca n elementi uguali
Cerca a partire dalla fine
C. Rocchini - C++
162
Algoritmi di Modifica
•
•
•
•
•
•
•
•
•
•
•
•
copy
swap
replace
replace_if
fill
generate
remove
remove_if
unique
reverse
rotate
random_shuffle
Copia di elemeni
Scambia due elementi
Rimpiazza un elemento con un altro
… con una condizione
Riempie con un valore
Riempie con una funzione
Rimuove un valore
.. Secondo una condizione
Toglie gli elementi duplicati !!
Inverte l’ordine
Ruota l’ordine
Mescolamento Casuale (*SGI ext.*)
C. Rocchini - C++
163
Ordinamenti
• sort
ordinamento! Spesso si usano
oggetti funtori per comparare gli oggetti
• lower_bound
ricerca binaria O(log(n))
• upper_bound
Ci sono molte altre cose (funtori), ma per ora
non le vedremo.
C. Rocchini - C++
164
Interfacce grafiche
• Es3: mfc
– Consultate i lucidi relativi
alla esercitazione 3:
applicazione grafica con
Microsoft Foundation Classes
C. Rocchini - C++
165
Esercitazioni ed Esempi
• Manipolazione di testi
• Database (odbc o MySql)
• Libtiff
• Cenni ad OpenGL
C. Rocchini - C++
166
Argomenti avanzati del C++
• Parametri non specificati
• Eccezioni
• Puntatori a funzioni
• Cast specificati
• Mutable
• Problemi dell’ereditarieta’
multipla
C. Rocchini - C++
167