Dal C al C++/Utilizzo basilare di librerie/L'uso dei namespace: differenze tra le versioni

Contenuto cancellato Contenuto aggiunto
G4Bot (discussione | contributi)
m Bot: Aggiungo: "{{Avanzamento|100%}} "
Nessun oggetto della modifica
Riga 7:
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 precedenza in quella unità di compilazione e che sono attivi in quelloquell'ambito (''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".
 
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. Ogni volta che si dichiara un identificatore, si aggiunge una voce alla symbol table.
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.
 
ma dalDal punto di vista del programmatore, gli identificatori vengono cercati nello "spazio dei nomi", o, in inglese, "namespace". Ogni volta che si dichiara un identificatore, si aggiunge una voce allo spazio dei nomi corrente.
 
Nel linguaggio C, i nomi hanno unoun scopeambito, 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.
Line 21 ⟶ 23:
Supponendo di non avere i sorgenti della libreria, l'unica possibilità è modificare l'applicazione.
 
La situazione è peggiore se abbiamo adottato due librerie non modificabili 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" (perche significa "standard").
 
Per accedere a un nomeidentificatore contenuto in un namespace dallda una funzione dichiarata all'interno del namespace stesso, non è richiesta nessuna sintassi particolare.
Quindi, chi sviluppa una libreria può dimenticarsi che gli identificatori della libreria verranno posti in un namespace.
 
PerInvece, per accedere a un nomeidentificatore contenuto in un namespace dall'esternoda deluna funzione esterna al namespace stesso, si deve invece ''qualificare'' il nomel'identificatore, facendolo precedere da nome del namespace, separato da due caratteri ":".
Per esempio, se dal codice applicativo si vuole usare l'oggetto "cout" e la classe "string" possonosi esserepuò usatiusare nelil seguente modocodice:
 
<source lang=cpp>
std::string s = "abc";
std::cout << s;
</source>
 
In tal modo, si comunica al compilatore che, anche se nel codice applicativo o in una libreria non standard fossero definiti un identificatore "string" e un identificatore "cout", non si vuol far riferimento a tali identificatori, ma a quelli facenti parte della libreria standard.
 
Per evitare di dover ripetere il nome del namespace ogni volta che si fa riferimento a un oggettoidentificatore di libreria, si può usare l'apposita direttiva seguente, dove N rappresenta il nome di un namespace:
Per accedere a un nome contenuto in un namespace dall'interno del namespace stesso non è richiesta nessuna sintassi particolare.
 
<source lang=cpp>
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 ":".
using namespace N;
Per esempio, l'oggetto "cout" e la classe "string" possono essere usati nel seguente modo:
</source>
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 è buonaappropriato regolaporre porlauna all'iniziodichiarazione di questo tipo appena dopo le direttive di inclusione di ogni unità di compilazione, appenache dopousa lequalche direttiveidentificatore di inclusionetale namespace.
 
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 ricorredovrà ricorrere alla qualificazione esplicita.
 
La direttiva "using namespace" non dovrebbe però essere usata mai né nei file di intestazione, né in una unità di compilazione prima di una direttiva di inclusione.
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.
Infatti, usandola prima di una direttiva di inclusione verrebbe applicata al contenuto del file incluso, e dato che un file incluso potrebbe includere direttamente o indirettamente molti altri file, applicandola a un file incluso potrebbe comportare che venga applicata ad alcuni file in cui provocherebbe conflitto.
 
[[Categoria:Dal C al C++|Namespace]]