Domanda

Perché abbiamo bisogno di entrambi utilizzando namespace e comprendono direttive in programmi C ++?

Ad esempio,

#include <iostream>

using namespace std;

int main() {
 cout << "Hello world";
}

Perché non è sufficiente avere solo # include o semplicemente "utilizzando namespace std" e di sbarazzarsi degli altri?

(mi pare di un'analogia con Java, import java.net. * Consente di importare import tutto da java.net, non c'è bisogno di fare altro.)

È stato utile?

Soluzione

In C++ i concetti sono separati. Ciò è di progettazione e utile.

È possibile includere le cose che senza spazi dei nomi sarebbe ambiguo.

Con spazi dei nomi è possibile fare riferimento a due classi diverse che hanno lo stesso nome. Naturalmente, in quel caso non sarebbe utilizzare la direttiva using o se l'avete fatto si dovrà indicare lo spazio dei nomi delle altre cose nello spazio dei nomi che si voleva.

Si noti inoltre che non è necessario l'utilizzo - si può solo utilizzare std :: cout o qualsiasi altra cosa è necessario accedere. È precedere gli elementi con lo spazio dei nomi.

Altri suggerimenti

l'uso di direttive e comprendono direttive del preprocessore sono due cose diverse. Il include corrisponde all'incirca alla variabile di ambiente CLASSPATH di Java, o l'opzione -cp della macchina virtuale Java.

Ciò che fa è rendere i tipi conosciuti al compilatore. Proprio tra cui <string> per esempio vi renderà in grado di fare riferimento a std::string:

#include <string>
#include <iostream>

int main() {
    std::cout << std::string("hello, i'm a string");
}

Ora, utilizzando le direttive sono come import in Java. Fanno nomi visibile nel perimetro appaiono in, in modo da non dover qualificare completamente loro più. Come in Java, i nomi utilizzati devono essere conosciuti prima che possano essere resi visibili:

#include <string> // CLASSPATH, or -cp
#include <iostream>

// without import in java you would have to type java.lang.String . 
// note it happens that java has a special rule to import java.lang.* 
// automatically. but that doesn't happen for other packages 
// (java.net for example). But for simplicity, i'm just using java.lang here.
using std::string; // import java.lang.String; 
using namespace std; // import java.lang.*;

int main() {
    cout << string("hello, i'm a string");
}

E 'cattiva pratica di usare una direttiva using nel file header, perché significa che tutti gli altri file di origine che succede a includere vedrà quei nomi che usano ricerca del nome non qualificato. A differenza di Java, dove si fa solo i nomi visibile al pacchetto della linea di importazione appare in, In C ++ può interessare l'intero programma, se includono il file direttamente o indirettamente.

Fate attenzione quando farlo in ambito globale, anche nei file di implementazione. Meglio di usarli come locale come possibile. Per namespace std, io non uso mai questo. Io, e molte altre persone, proprio sempre scrivere std:: davanti a nomi. Ma se vi capita di farlo, farlo in questo modo:

#include <string>
#include <iostream>

int main() {
    using namespace std;
    cout << string("hello, i'm a string");
}

Per quanto spazi dei nomi sono e perché ne avete bisogno, si prega di leggere la proposta Bjarne Stroustrup ha dato 1993 aggiungendoli al prossimo standard C ++. E 'ben scritto:

http: //www.open- std.org/jtc1/sc22/wg21/docs/papers/1993/N0262.pdf

In C ++ #include e con funzioni diverse.

#include mette il testo del file incluso nel file sorgente (in realtà unità di traduzione ) , gli spazi dei nomi invece sono solo un meccanismo per avere nomi univoci in modo che persone diverse possono creare un oggetto "foo".

Questo deriva dal C ++ non avere il concetto di un modulo.

Tenga presente che namespace in C ++ sono aperti, il che significa che i file differenti possono definire diverse parti di uno stesso spazio dei nomi (un po 'come classi parziali del NET).

//a.h
namespace eg {
    void foo();
}

//b.h
namespace eg {
    void bar();
}

Il comprendono sta definendo l'esistenza delle funzioni.

L'utilizzo sta rendendo più facile usarli.

cout come definito nella iostream in realtà si chiama "std :: cout".

Si potrebbe evitare di utilizzare lo spazio dei nomi scrivendo.

std::cout << "Hello World";

Queste parole chiave vengono utilizzati per scopi diversi.

La parola chiave utilizzando lo rende un nome da uno spazio dei nomi disponibili per l'uso nella regione dichiarativa corrente. La sua principalmente per comodità in modo che non è necessario utilizzare il nome completo per tutto il tempo. Questo pagina lo spiega in dettaglio.

L'istruzione #include è una direttiva pre processore e dice al preprocessore per trattare il contenuto di un file specificato, come se quei contenuti erano apparsi nel programma di origine nel punto in cui appare la direttiva. Cioè, si può pensare di questa affermazione come copiare il file incluso in quello corrente. Il compilatore quindi compila l'intero file come se hai scritto tutto il codice in un unico grande file.

Credo che le altre risposte mancano un po 'il punto. In tutti C ++, Java e C #, la cosa using / import è del tutto facoltativo. Quindi questo non è diverso.

E poi si deve fare qualcosa di diverso per rendere il codice sia visibile in ogni caso, in tutte e tre le piattaforme.

In C ++, si deve minimamente includerlo nella unità di traduzione corrente (abbastanza buono per molte implementazioni di vettore, archi, ecc), spesso si deve aggiungere qualcosa al vostro linker pure, anche se alcune librerie fanno automaticamente sulla base del includere (ad esempio spinta quando sulla base di Windows).

E in C # è necessario aggiungere un riferimento l'altro gruppo. Che si occupa di l'equivalente di include e le impostazioni di collegamento.

E in Java è necessario assicurarsi che il codice è nel classpath, per esempio aggiungendo il vaso relativo ad esso.

Quindi ci sono cose strettamente analoghi necessari su tutte tre le piattaforme, e la separazione tra using / import (per comodità) e la risoluzione effettiva tirante (un requisito) è la stessa in tutti e tre.

Come sottolineato, C ++ e Java sono linguaggi diversi, e fare le cose un po 'diverse. Inoltre, C ++ è più di un 'scherzo cresciuto' la lingua, e Java più di un linguaggio progettato.

Mentre using namespace std; non è necessariamente una cattiva idea, usarlo per tutti gli spazi dei nomi eliminerà tutto il beneficio. I namespace esistono in modo che è possibile scrivere moduli senza riguardo al nome di scontri con altri moduli, e using namespace this; using namespace that; possibile creare ambiguità.

È necessario capire namespace se si vuole capire veramente questo.

Con include si sono appena compreso il file di intestazione.

Con using namespace si dichiara che si sta utilizzando un determinato spazio dei nomi che contiene cose come cout. quindi se si fa questo:

using namespace std;

per utilizzare cout si può solo fare

cout << "Namespaces are good Fun";

invece che:

std::cout << "Namespaces are Awesome";

Si noti che se non si #include <iostream> non sarà in grado di utilizzare né std::coutcout nelle vostre dichiarazioni e così via, perché non stai inclusa l'intestazione.

Una nave di linea (non che questo è qualcosa di nuovo:)):

utilizzando std consente di saltare il std :: prefisso, ma non è possibile utilizzare cout a tutti, senza iostream .

Anche Stroustrup riferisce al meccanismo #include come piuttosto hackish. Tuttavia lo fa fare compilazione separata molto più facile (nave compilato librerie e header invece di tutto il codice sorgente).

La questione è davvero "Perché C ++ - dopo che già aveva il meccanismo #include -? Aggiungere spazi dei nomi"

L'esempio migliore che io conosca sul perché #include non è sufficiente viene da Sun. A quanto pare gli sviluppatori Sun avuto qualche problema con uno dei loro prodotti perché avevano scritto una funzione mktemp() che è capitato di avere la stessa firma in funzione mktemp() che è stato incluso attraverso da un file che è stato esso stesso incluso attraverso un colpo di testa il progetto in realtà voleva.

Naturalmente le due funzioni non erano compatibili, e non possono essere usati come sostituto per l'altro. D'altra parte, il compilatore e il linker non si rendono conto di questo quando si costruisce il binario, e talvolta mktemp() chiamerebbero una funzione, e talvolta sarebbe chiamare un altro, in base ai diversi file di ordine sono stati compilati o collegato.

Il problema deriva dal fatto che il C ++ in origine era compatibile con - ed essenzialmente piggy-backed in cima - C. e C ha solo un namespace globale. C ++ risolto questo problema - nel codice che non è compatibile con C -. Attraverso namespace

Sia C # e Java (1) hanno un meccanismo di namespace (namespace in C #, package in Java), (2) di solito sono sviluppate attraverso IDE che gestiscono riferendosi binari per lo sviluppatore, e (3) non consentono freestanding funzioni (un ambito di classe è una sorta di spazio dei nomi, e riduce il rischio di inquinare il namespace globale) in modo da avere una soluzione diversa a questo problema. Tuttavia, è ancora possibile avere una certa ambiguità per quanto riguarda il metodo che si sta chiamando (ad esempio, uno scontro tra il nome di due interfacce che una classe eredita), e in questo caso tutte e tre le lingue richiede al programmatore di specificare in modo chiaro quale metodo sono in realtà cercando, di solito anteponendo il nome della classe genitore / interfaccia.

In C ++, la direttiva include sarà copiare e incollare il file di intestazione nel codice sorgente nella fase di pre-elaborazione. Va notato che un file di intestazione contiene in genere funzioni e le classi dichiarate all'interno di uno spazio dei nomi. Ad esempio, l'intestazione <vector> potrebbe essere simile a qualcosa di simile:

namespace std {
    template <class T, class Allocator = allocator<T> > class vector;
    ...
} 

Supponendo è necessario definire un vettore nella funzione principale, fare #include <vector> e si ha il pezzo di codice di cui sopra nel codice ora:

namespace std {
    template <class T, class Allocator = allocator<T> > class vector;
    ...
}
int main(){
   /*you want to use vector here*/
}

Si noti che nel codice della classe vettore si trova ancora nello spazio dei nomi std. Tuttavia, la funzione principale è nello spazio dei nomi di default global, così semplicemente con l'indicazione dell'header non farà la classe Vector visibile in global namespace. La pagina può essere utilizzare per using o non anteponendo come std::vector.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top