Dal C al C++/Utilizzo basilare di librerie/Dichiarazioni e definizioni: differenze tra le versioni

Contenuto cancellato Contenuto aggiunto
Nonostante le apparenze, ho cambiato solo l'indentazione e ho aggiunto numerose volte il tag <source lang=cpp>
Riga 221:
 
Il seguente programma è errato in C, ma valido in C++:
<source lang="cpp">
double f(int x) { return (double)x; }
double f(float x) { return (double)x * 3; }
int main() {
double a = f(7);
double b = f(7.f);
}
}</source>
Alla variabile "a" viene assegnato il valore "7.0", mentre alla variabile "b" viene assegnato il valore "21.0".
 
Line 241 ⟶ 243:
 
Il sovraccaricamento può dare origine ad ambiguità, come nel seguente programma errato:
<source lang="cpp">
void f(double x) { }
void g(float x) { }
void g(double x) { }
int main() {
f(7);
g(7); // Illegale
}
}</source>
La prima istruzione chiama la funzione "f" passandole un valore di tipo "int".
Non esistono funzioni di nome "f" e con un parametro di tipo "int", ma ne esiste una con nome "f" e un parametro di tipo "double", ed esiste una conversione standard da "int" a "double".
Line 259 ⟶ 263:
Per evitare tale errore, in presenza di più funzioni sovraccaricate, si deve passare una parametro avente uno dei tipi per cui esiste la funzione sovraccaricata.
Per esempio, quell'istruzione avrebbe dovuto essere una delle due seguenti:
<source lang="cpp">
g(7.f); // Chiama g(float)
g(7.); // Chiama g(double)
</source>
oppure una delle due seguenti:
<source lang="cpp">
g((float)7); // Chiama g(float)
g((double)7); // Chiama g(double)
</source>
 
=== L' Overloading degli operatori ===
Line 272 ⟶ 280:
 
Si consideri il seguente programma:
<source lang="cpp">
#include <iostream>
#include <complexiostream>
#include <complex>
using namespace std;
int main() {
complex<double> c1, c2;
cout << (c1 + c2);
}
</source>
Nell'ultima riga si usano l'operatore di ''scorrimento a sinistra'' "<<" e l'operatore di ''somma'' "+".
 
Line 292 ⟶ 302:
 
Sia in C che in C++, si può scrivere la seguente porzione di codice:
<source lang="cpp">
int a = 1; // Variabile globale inizializzata esplicitamente
static int ba = 21; // Variabile di moduloglobale inizializzata esplicitamente
static int cb = 2; // Variabile globaledi modulo inizializzata implicitamenteesplicitamente
static int dc; // Variabile di moduloglobale inizializzata implicitamente
static int a(1)d; // Variabile globaledi modulo inizializzata esplicitamenteimplicitamente
int funz() {
int e = 1; // Variabile locale temporanea inizializzata esplicitamente
static int f = 2; // Variabile locale statica inizializzata esplicitamente
int g; // Variabile locale temporanea non inizializzata
static int h; // Variabile locale statica inizializzata implicitamente
}
</source>
In questo codice, vengono allocate staticamente le variabili "a", "b", "c", "d", "f", "h", mentre vengono allocate sullo stack le variabili "e" e "g".
Line 324 ⟶ 336:
 
Il C++ introduce una nuova sintassi per inizializzare oggetti. Ecco un esempio:
<source lang=cpp>
int a(1); // Variabile globale inizializzata esplicitamente
static int ba(21); // Variabile di moduloglobale inizializzata esplicitamente
static int a = 1b(2); // Variabile globaledi modulo inizializzata esplicitamente
int funz() {
int e(1); // Variabile locale temporanea inizializzata esplicitamente
static int f(2); // Variabile locale statica inizializzata esplicitamente
}
</source>
Invece di scrivere "= espressione", si scrive "( espressione )".
L'effetto è identico, cambia solo la sintassi, che somiglia a quella della chiamata di funzione.
La motivazione di questa nuova sintassi sta nel seguente programma d'esempio:
<source lang=cpp>
#include <complex>
#include <iostreamcomplex>
#include <iostream>
using namespace std;
complex<double> a(3, 4);
int main() {
cout << a;
}
</source>
Lanciando questo programma viene stampato sulla console "(3,4)", che è la rappresentazione testuale del numero complesso rappresentato dalla variabile "a".
 
Line 348 ⟶ 364:
Ovviamente il numero di parametri dell'inizializzatore dipende dal tipo dell'oggetto da inizializzare.
Le due righe seguenti sono errate:
<source lang=cpp>
int a(3, 4); // Illegale: un parametro di troppo
complex<double>int ba(3, 4, 5); // Illegale: un parametro di troppo
intcomplex<double> ab(3, 4, 5); // Illegale: un parametro di troppo
</source>
 
Le funzioni possono avere più di un parametro, ma possono anche non averne nessuno.
Che cosa significano le due espressioni seguenti?
<source lang=cpp>
int a();
int a();
complex<double> b();
</source>
 
Purtroppo non sono affatto dichiarazioni di variabili, ma prototipi di funzione, in quanto lo erano già in linguaggio C.
Line 363 ⟶ 383:
 
Ma che cosa stampa questo programma?
<source lang=cpp>
#include <complex>
#include <iostreamcomplex>
#include <iostream>
using namespace std;
int main() {
int amain(); {
int a;
complex<double> b;
cout << a << " " << b;
}
</source>
Verrà stampato il valore di un numero intero, seguito da uno spazio, seguito dalla rappresentazione di un numero complesso.
Ma quali sono questi valori?
Line 385 ⟶ 407:
 
Per fare altri esempi, il seguente programma stampa sicuramente "[0,]":
<source lang=cpp>
#include <iostream>
#include <stringiostream>
#include <vectorstring>
#include <complexvector>
using namespace std;
int main() {
int main() {
vector<int> v;
string s;
cout << "[" << v.size() << "," << s << "]";
}
</source>
L'espressione "v.size()" genera il numero di elementi contenuti nel vettore "v"; il fatto che venga stampato "0" è segno del fatto che la variabile "v" è stata inizializzata ad uno stato in cui non contiene nessun elemento.
 
Line 414 ⟶ 438:
La variabile potrà essere utilizzata solo dopo il punto in cui è stata definita, fino alla chiusa del blocco più interno nel quale è stata definita.
Vediamo un esempio:
<source lang=cpp>
void f() {
int a;
a = 0;
Line 422 ⟶ 447:
int c;
{
int d;
d = 0;
static int e;
}
d = 0; // Illegale, qui "d" è già stata deallocata
e = 0; // Illegale, qui "e" esiste ancora, ma non è più accessibile
}
</source>
 
All'interno di una struttura o di una classe, è possibile usare il qualificatore "static" per una variabile membro.
Per esempio:
<source lang=cpp>
#include <iostream>
using namespace std;
struct C {
int a;
static int b;
};
int C::b;
int main() {
C c1;
c1.a = 1;
Line 447 ⟶ 474:
c2.b = 4;
cout << c1.a << " " << c1.b << " " << c2.a << " " << c2.b;
}
</source>
 
Questo programma non stampa "1 2 3 4", come avrebbe fatto se la variabile membro "b" non fosse stata statica.
Line 456 ⟶ 484:
 
Si noti che dopo la definizione della struttura C, c'è la seguente riga:
<source lang=cpp>
int C::b;
</source>
Questa è la "definizione" della variabile membro "b", che era stata solo "dichiarata" nella struttura C.
 
Line 478 ⟶ 508:
Il suo fine è indicare al compilatore dove cercare il nome indicato alla sua destra.
Alla sinistra di tale operatore ci può essere il nome di una struttura o classe, oppure il nome di un namespace (come "std"), oppure anche niente, come nella seguente istruzione.
<source lang=cpp>
::a = 3;
</source>
Questa istruzione assegna il valore 3 alla variabile globale di nome "a".
L'operatore serve a indicare che tale il variabile non deve essere confusa con eventuali variabili locali o parametri di funzione con lo stesso nome.