Richiami di linguaggio C
++• Struttura di un file sorgente:
// file di intestazione predefiniti
#include <file intestazione>
// file di intestazione definiti dall’utente
#include "file intestazione"
#direttive al preprocessore
dichiarazioni globali; // meno possibili di queste int main() {
dichiarazioni locali;
istruzioni;
funzioni(parametri);
return intero;
}
• file d’intestazione
Contengono le definizioni delle funzioni. I pi`u comuni sono iostream per fare input e output, iomanip per formattare l’output, cmath per usare le funzioni matematiche. I file d’intestazione del linguaggio C si possono usare come sono (esempio <stdio.h>) oppure premettendo una ”c” e togliendo
”.h” (<cstdio>)
• dichiarazione di funzioni e variabili a livello di file
Prima di main definisco le variabili e le funzioni visibili da tutto il programma.
All’interno di ogni funzione posso definire variabili che sono visibili solo in quella funzione (locali).
• programma principale: int main(argc, argv[]). argv[] con- tiene gli argomenti passati sulla linea di comando, argc `e il loro numero. argv[0] contiene sempre il nome del pro- gramma eseguibile
• tipi principali di dati: int e long, float e double, char e loro puntatori int * e long * , float * e double *, char *
• puntatori: sono gli indirizzi delle variabili e degli array: se p[100] `e un array di interi, p `e un puntatore a intero. vice- versa se p punta ad un valore a, scrivo *p=a oppure p=&a.
• funzioni
- ritornano un valore (se non void)
- gli argomenti sono passati per valore, per puntatore o per riferimento.
- se la funzione deve modificare il valore dei propri argo- menti, questi devono essere passati come puntatori o riferi- menti alle variabili da cambiare.
- ogni funzione deve avere una dichiarazione, di solito all’inizio del file o in un file d’intestazione incluso, ed una definizione (dove si spiega cosa effettivamente fa la funzione).
Esempio:
//dichiarazione, di solito all’inizio del file sorgente double fun(int n, double x);
//definizione
double fun(int n, double x) {
return pow(x,n);
}
Le funzioni possono avere lo stesso nome se gli argomenti (parametri) sono diversi. Esempio
double fun(double x);
double fun(int x);
• operatori fondamentali =,+,-,/,*
Strutture fondamentali
Due strutture costituiscono il 90 per cento dei programmi scientifici
cicli
for(int j=0; j<10; j++) { cout<<"j vale "<<j<<endl;
}
• Altri cicli sono while(condizione){...} e
do{...}while(condizione);. La seconda esegue il ciclo almeno una volta;
• per uscire da un ciclo si usa break;
• per passare alla prossima iterazione del ciclo si usa continue.
istruzioni condizionali if(j==3) {
cout<<"J vale 3\n";
}
else if(j==2) {
cout<<"J vale 2\n";
}
else cout<<"J non vale 2 o 3\n";
Un’altra istruzione condizionale `e switch...case:
Le condizioni sono espresse tramite gli operatori
==, !=, <, >, <=, >=
nota bene: == non `e =
Alcune funzioni matematiche
xy = pow(x,y)
√x = sqrt(x)
ex = exp(x)
sin(x) = sin(x) cos(x) = cos(x) tan(x) = tan(x) sin−1(x) = asin(x) cos−1(x) = acos(x) tan−1(x) = atan(x)
floor(x) = massimo intero che non supera x fabs(x) = |x|
- Un’altra operazione importante `e il resto della divisione per un numero
- Per gli interi i%5 da’ il resto della divisione di i per 5
- Per i reali fmod(x,3.14) da’ il resto della divisione di x per 3.14.
- Per usare tutte queste funzioni bisogna includere hcmathi e linkare -lm
Costanti
Un modo per ottenerle `e
π = 4 · arctan(1.) e = exp(1.)
Uno pi`u standard `e guardare le definizioni nel file math.h
π = M P I e = M E
√2 = M SQRT 2
infine, il metodo forse pi`u sicuro, consiste nel definire per conto nostro la costante all’inizio del file
const double PI = 3.14159265
oppure, ancora meglio, nella classe in cui la utilizziamo, come static const double PI = 3.14159265
Overloading delle funzioni
Una funzione `e definita dal valore che ritorna, dal numeri e dal tipo degli argomenti. Le due funzioni seguenti non coincidono int square(int x)
{
return x*x;
}
double square(double x) {
return x*x;
}
-Anche se il codice `e identico, le funzioni hanno un diverso tipo di parametri, e vengono considerate diverse dal compilatore: questa caratteristica si chiama overloading (sovraccarico)
- Un esempio di funzioni sovvraccariche sono gli operatori, come la somma, che possono operare su tipi diversi. Definendo nuovi tipi di dati `e possibile definire in modo personalizzato la somma, la differenza, il prodotto di due dati.
- Il compilatore sceglie da solo quale delle funzione utilizzare, in base al tipo di parametri passati; questo vale anche per l’operatore di output <<
Classi
Le classi sono forse il maggior punto di forza del C++ perch´e permettono una pi`u chiara organizzazione del codice. Una classe
`e un contenitore in cui possono stare due tipi di oggetti: i dati e i metodi. Per fare un esempio, la classe ”Torta di mele” contiene la farina, l’acqua, le mele e lo zucchero, pi`u il metodo per fare l’impasto e il metodo per cuocere. Se volte fare una buona torta di mele C++, non potete accedere direttamente alla farina e agli altri ingredienti (che si dicono private ma potete impastarla e cuocerla (diciamo che questi metodi sono public). Se x e y sono entrambi torte di mele, diciamo che ciascuno `e un’istanza della classe.
Esempio: una classe di numeri complessi
class Complesso {
private:
double r // parte reale
double i // parte immaginaria public:
// funzioni membro della classe // dichiarate e definite insieme // chiamato con z.abs()
double abs(void) {return sqrt(r*r+i*i);}
//chiamato con z.sum(z2)
void sum(Complesso z2) {r += z2.r; i += z2.i;}
}
void Complesso::sub(z2) {r -= z2.r; i -= z2.i;}
Static
Questa parola chiave indica tre cose diverse a seconda del con- testo
• a livello di file indica che la variabile `e visibile solo all’interno di quel file: ovviamente questo ha senso solo per programmi composti da pi`u file sorgente;
• in una classe, riferito ad una variabile, indica che esiste una sola copia di quella variabile nella classe, e non una copia per ogni istanza. Se, ad esempio, voglio utilizzare una costante nella classe, non `e utile averne una copia per ogni istanza;
• in una classe, riferito alle funzioni, indica che la funzione non riceve la classe come parametro. Ad esempio, se f1 e f2 sono nella classe c, ma f2 `e statica, le chiamate saranno del tipo c.f1(pa1, par2) e f2(par1, par2).
Const
Anche questa parola chiave indica (almeno) tre cose diverse a seconda del contesto
• Posta nella dichiarazione di un attributo di una classe indica che questo non pu`o mai essere cambiato, quindi deve essere inizializzato al momento della dichiarazione. Esempio:
const double PI=3.14159;
• posto dopo la dichiarazione di una funzione di una classe, in- dica che la funzione non cambier`a mai gli attributi dell’oggetto su cui viene chiamato. Esempio:
class A {
private:
int i;
public:
double f(i) const {
return i+3.0; // non cambia il valore di i }
};
• in una generica funzione, indica che un parametro non viene cambiato dalla funzione; `e utile quando conviene passare un parametro per riferimento o puntatore, ma senza volerlo modificare. Esempio:
arr = new double(1000000);
double sumElements(const double & arr) {
double sum = 0.0;
for(int j=0; j<1000000; j++) sum += arr[j];
return sum;
}
this
this `e un puntatore alla classe di cui una funzione fa parte. Se c `e una classe, f una funzione non statica che gli appartiene e i un’istanza della classe, allora i.f(argomenti) `e lo stesso che f(this,argomenti) dove this punta a i Le funzioni statiche non ricevono il puntatore this come argomento.
Questo corso trascura qualcosa del C
++?
In questo corso non si parla di
• ereditariet`a;
• polimorfismo;
• eccezioni;
• funzioni virtuali;
• classi astratte.
che sono argomenti avanzati non utilizzati nel corso.