Dal C al C++/Introduzione: differenze tra le versioni

Contenuto cancellato Contenuto aggiunto
Ramac (discussione | contributi)
m Annullate le modifiche di 62.10.173.191, riportata alla revisione precedente di Pietrodn
Riga 104:
== Panoramica ==
 
Il C++, come il C, è ''non è completamente specificato'', nel senso che numerose espressioni sintatticamente corrette, e quindi ammesse dal compilatore, non hanno una semantica definita, e quindi in fase di esecuzione possono produrre risultati dipendenti dall'implementazione del compilatore, se non addirittura risultati variabili da un'esecuzione all'altra.
Per esempio, si consideri questo programma, valido sia in C che in C++:
 
void f(int a, int b) { }
<source lang=cpp>
int g() { return 1; }
intvoid hf()int {a, returnint 2;b) { }
int maing() { return 1; }
int h() { return 2; }
int main() {
f(g(), h());
*(char *)0 = 3;
}
</source>
 
Nella prima istruzione della funzione "main", sia il C che il C++ non definiscono se verrà chiamata prima la funzione "g" o la funzione "h".
Line 130 ⟶ 133:
 
Ecco un programma C++ che esemplifica l'utilizzo di tutte le suddette caratteristiche:
 
#include <iostream>
<source lang=cpp>
#include <vector>
#include <complexiostream>
#include <vector>
using namespace std;
#include <complex>
int main() {
using namespace std;
complex<double> c1(2, 3); // c1 è un numero complesso
int main() {
complex<double> *pc2; // pc2 è un puntatore a un numero complesso
complex<double> c1(2, const string s = "Risultato: "3); // sc1 è un oggettonumero stringacomplesso
complex<double> *pc2; // pc2 è un puntatore a un numero complesso
try {
const string s = "Risultato: "; // s è un oggetto stringa
pc2 = new complex<double>(5, min(17, 12));
} catch (...)try {
pc2 cerr= new complex<<double>(5, "Memoriamin(17, insufficiente\n"12));
} catch (...) return 1;{
cerr << "Memoria insufficiente\n";
}
return 1;
}
vector<complex<double> > vcd;
vcd.push_back(c1 + *pc2);
cout << s << vcd.front();
delete pc2;
}
</source>
 
Diciamo subito che cosa fa questo programma.
Line 157 ⟶ 163:
Data la concentrazione di molti concetti disparati, il lettore non si spaventi se non tutto risultasse chiaro.
 
<source lang=cpp>
#include <iostream>
#include <iostream>
</source>
 
Questa riga include le dichiarazioni della libreria di ingresso/uscita su canali (stream input/output), nonché gli oggetti su cui si basa l'ingresso/uscita su console. Ha la stessa finalità del file "stdio.h" della libreria standard del linguaggio C.
Si noti che manca l'estensione ".h" dopo "iostream".
 
<source lang=cpp>
#include <vector>
#include <vector>
</source>
 
Questa riga include le dichiarazioni della libreria che gestisce gli array a dimensione dinamica, chiamati appunto "vector".
 
<source lang=cpp>
#include <complex>
#include <complex>
</source>
 
Questa riga include le dichiarazioni della libreria di gestione dei numeri complessi.
Ricordiamo che i numeri complessi sono entità matematiche rappresentabili come coppie di numeri reali: la parte reale e la parte immaginaria.
Line 170 ⟶ 185:
La somma di due numeri complessi ha come parte reale la somma delle parti reali e come parte immaginaria la somma delle parti immaginarie.
 
<source lang=cpp>
using namespace std;
using namespace std;
</source>
 
Questa riga dichiara che d'ora in poi in questa unità di compilazione, ogni identificatore verrà cercato non solo nello spazio dei nomi globale (cioè quello del linguaggio C), ma anche nello spazio dei nomi "std", cioè quello della libreria standard del C++.
 
<source lang=cpp>
int main() {
int main() {
</source>
 
Questa riga definisce il punto di ingresso del programma, analogamente ai programmi in linguaggio C.
La differenza sta nel fatto che il valore di ritorno è obbligatoriamente "int", ma, a differenza di tutte le altre funzioni che rendono un "int" è consentito omettere l'istruzione di return in fondo alla funzione, sottintendendo "return 0;".
 
<source lang=cpp>
complex<double> c1(2, 3);
complex<double> c1(2, 3);
</source>
 
Questa riga definisce sullo stack una variabile identificata dal nome "c1", il cui tipo è "complex<double>", e che è inizializzata con la coppia di valori "2, 3".
Il tipo "complex<double>" rappresenta un numero complesso in cui sia la parte reale che la parte immaginaria sono memorizzate in numeri a virgola mobile di tipo "double".
Line 192 ⟶ 216:
La sintassi è analoga a quella di una chiamata di funzione.
 
<source lang=cpp>
complex<double> *pc2;
complex<double> *pc2;
</source>
 
Questa riga definisce sullo stack un puntatore di nome "pc2", che può contenere l'indirizzo di un oggetto del tipo "complex<double>", appena visto.
Tale variabile (puntatore) non è inizializzata, pertanto il suo contenuto è indefinito, e sarebbe un errore logico usarne il valore prima di assegnargli un valore valido.
 
<source lang=cpp>
const string s = "Risultato: ";
const string s = "Risultato: ";
</source>
 
Questa riga definisce sullo stack una variabile di nome "s", di tipo "const string", inizializzata dalla costante di stringa "Risultato: ".
 
Line 206 ⟶ 236:
L'inizializzazione segue lo stile delle inizializzazioni in linguaggio C.
Una sintassi alternativa ma equivalente sarebbe stata la seguente:
 
const string s("Risultato: ");
<source lang=cpp>
const string s("Risultato: ");
</source>
 
Se l'inizializzatore è uno solo, è possibile scegliere tra le due notazioni; mentre se se ci sono più inizializzatori, come nel caso della variabile "c1" sopra, è ammessa solo la notazione funzionale.
 
<source lang=cpp>
try {
try {
</source>
 
Questa riga inizia un blocco "try", utilizzato per la gestione delle eccezioni.
Per ''eccezione'' si intende una situazione anomala rilevata all'interno di una funzione di libreria, e a causa della quale la funzione stessa non è in grado di completare il suo compito. Per segnalare al chiamante il proprio fallimento, la funzione termina ''sollevando'' un'eccezione.
Line 215 ⟶ 252:
Quando in codice contenuto all'interno di un blocco "try" solleva un'eccezione, il controllo passa immediatamente alla fine del blocco "try" stesso, dove c'è il blocco "catch".
 
<source lang=cpp>
pc2 = new complex<double>(5, min(17, 12));
pc2 = new complex<double>(5, min(17, 12));
</source>
 
Questa riga contiene una chiamata all'operatore "new", che è l'operatore predefinito per allocare dinamicamente oggetti nella memoria libera.
 
Line 229 ⟶ 269:
Non si tratta di una semplice funzione, ma di un template di funzione, in quanto, al variare del tipo degli argomenti, rappresenta una funzione diversa. In questo caso, è una funzione che prende due espressioni di tipo "int" e rende un valore di tipo "int".
 
<source lang=cpp>
} catch (...) {
} catch (...) {
</source>
 
Questa riga inizia il blocco "catch" dell'istruzione "try/catch".
Se all'interno del blocco "try" precedente viene sollevata un'eccezione, il controllo passa all'interno di questo blocco, che quindi costituisce il gestore dell'eccezione.
 
<source lang=cpp>
cerr << "Memoria insufficiente\n";
cerr return<< 1"Memoria insufficiente\n";
return 1;
</source>
 
Queste due righe costituiscono il corpo del blocco "catch" e vengono eseguite solo se nell'esecuzione del blocco "try" viene sollevata un'eccezione.
 
Line 248 ⟶ 294:
Siccome "cerr" è un canale collegato alla console, l'effetto è di stampare la stringa sulla console.
 
<source lang=cpp>
vector<complex<double> > vcd;
vector<complex<double> > vcd;
</source>
 
Questa riga definisce sullo stack una variabile di nome "vcd" e di tipo "vector<complex<double> >", senza inizializzarla esplicitamente.
 
Line 261 ⟶ 310:
Pertanto, appena dopo questa dichiarazione, l'oggetto rappresentato dalla variabile "vcd" contiene un array dinamico di numeri complessi a precisione ''double'', che non contiene ancora nessun elemento.
 
<source lang=cpp>
vcd.push_back(c1 + *pc2);
vcd.push_back(c1 + *pc2);
</source>
 
Questa riga applica all'oggetto "vcd" la ''funzione membro'' (chiamata anche ''metodo'') "push_back", passandole un parametro.
 
Line 273 ⟶ 325:
Il numero complesso generato dalla somma viene subito dopo aggiunto in fondo al ''vector'' "vcd".
 
<source lang=cpp>
cout << s << vcd.front();
cout << s << vcd.front();
</source>
 
Questa riga usa un altro oggetto di tipo canale su console, "cout", che rappresenta il canale di uscita su console ("COUT" sta per Console OUTput stream).
Corrisponde al canale "stdout" della libreria standard del linuaggio C, dichiarato nel file di intestazione "stdio.h".
Line 288 ⟶ 343:
Come si vede, l'operatore di inserimento in canale ("<<") non accetta solo stringhe, ma anche altri tipi; in questo caso un'espressione di tipo "complex<double>".
 
<source lang=cpp>
delete pc2;
delete pc2;
</source>
 
Questa riga distrugge dalla memoria dinamica l'oggetto il cui indirizzo si trova nel puntatore "pc2".