Dal C al C++: differenze tra le versioni

Contenuto cancellato Contenuto aggiunto
Nessun oggetto della modifica
Nessun oggetto della modifica
Riga 494:
la seconda e la terza sono valide anche in linguaggio C.
La quarta versione usa una sintassi di type-cast introdotto dal C++, e equivalente a quella della terza versione.
 
== Uso dei namespace ==
 
Notoriamente, quando si vuole utilizzare una libreria, si devono prima chiarare le funzioni esportate (cioè pubblicate) da tale libreria.
 
Normalmente, invece di inserire a mano nel proprio codice le dichiarazioni delle funzioni che si intende utilizzare, ci si limita a include uno (o più) file di intestazione che contiene le dichiarazioni necessarie, usando la direttiva "#include" del preprocessore.
Tipicamente, tali file di intestazione non contengono solo dichiarazioni di funzioni, ma anche di variabili, costanti, tipi, strutture e, in C++, classi, template di classe e template di funzione.
Insomma, includendo un file di intestazione si mette a disposizione del programmatore una gran quantità di identificatori.
 
Quando il compilatore trova un identificatore, cerca tale identificatore tra tutti quelli che sono stati dichiarati in quella unità di compilazione e in quello ''scope''.
Dal punto di vista del compilatore, gli identificatori vengono cercati in una struttura dati che tradizionalmente si chiama "symbol table", anche se non ha necessariamente la forma di una tabella.
ma dal punto di vista del programmatore, gli identificatori vengono cercati nello "spazio dei nomi", o, in inglese, "namespace".
 
Nel linguaggio C, i nomi hanno uno scope, cioè possono essere locali o globali, ma gli oggetti globali appartengono tutti allo stesso spazio dei nomi.
 
Questo fatto crea problemi quando si vuole incominciare ad usare una nuova libreria in un programma esistente, o, peggio, quando si vogliono usare due o più librerie progettate indipendentemente.
 
Supponiamo che stiamo sviluppando un software che riguarda l'elettronica o l'elettrotecnica, e di usare per una funzione l'identificatore "socket" per indicare, in inglese, un dispositivo fisico a cui fa riferimento l'applicazione.
 
Ad un certo punto vogliamo aggiungere all'applicazione una funzionalità di comunicazione di rete, e utilizziamo una libreria che usa il medesimo nome "socket" per indicare un canale di comunicazione.
Abbiamo una collisione di nomi, dalla quale si può uscire effettuando una ricerca e sostituzione globale nella libreria o nella nostra applicazione.
Supponendo di non avere i sorgenti della libreria, l'unica possibilità è modificare l'applicazione.
 
La situazione è peggiore se abbiamo adottato due librerie che utilizzano lo stesso nome per concetti diversi, o comunque non intercambiabili.
In tal caso il conflitto di nomi è insanabile.
 
È per rimediare a tale situazione che in C++ sono stati introdotti i namespace.
 
Ogni libreria ben progettata dovrebbe inserire tutti i nomi che dichiara all'interno di un namespace.
Per esempio, la famosa libreria Boost, inserisce tutte le proprie dichiarazioni nel namespace "boost".
 
La stessa libreria standard del C++ inserisce gran parte delle proprie dichiarazioni nel namespace "std" (per "standard").
 
Per accedere a un nome contenuto in un namespace dall'interno del namespace stesso non è richiesta nessuna sintassi particolare.
 
Per accedere a un nome contenuto in un namespace dall'esterno del namespace, si deve invece ''qualificare'' il nome, facendolo precedere da nome del namespace, separato da due caratteri ":".
Per esempio, l'oggetto "cout" e la classe "string" possono essere usati nel seguente modo:
std::string s = "abc";
std::cout << s;
 
Per evitare di dover ripetere il nome del namespace ogni volta che si fa riferimento a un oggetto di libreria, si può usare l'apposita direttiva seguente, dove N rappresenta il nome di un namespace:
using namespace N;
Dopo tale direttiva, tutti i nomi contenuti nel namespace N possono essere utilizzati senza necessità di qualificazione.
Pertanto è buona regola porla all'inizio di ogni unità di compilazione, appena dopo le direttive di inclusione.
 
Ovviamente nei casi, non molto comuni, in cui in uno stesso file si usano due o più librerie che dichiarano uno stesso nome, non si potrà usare tale direttiva in tale file, in quanto provocherebbe un conflitto.
In tali casi si ricorre alla qualificazione esplicita.
 
Nei file di intestazione, invece è buona regola usare sempre la qualificazione esplicita, e non usare mai la direttiva "using namespace", in quanto tale direttiva si applicherebbe a tutte le unità di compilazione che, direttamente o indirettamente, includono tale file di intestazione.
 
{{wikipedia|titolopedia=C plus plus|titolobooks=il linguaggio C++}}