Pregunta

¿Por qué necesitamos usar espacios de nombres e incluir directivas en los programas C++?

Por ejemplo,

#include <iostream>

using namespace std;

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

¿Por qué no es suficiente tener #include o simplemente tener "usar el espacio de nombres std" y deshacerse del otro?

(Pienso en una analogía con Java, import java.net.* Importaré que importe todo de java.net, no necesita hacer nada más).

¿Fue útil?

Solución

En C++ los conceptos están separados. Esto es por diseño y útil.

Puede incluir cosas que sin espacios de nombres sería ambiguo.

Con espacios de nombres se puede hacer referencia a dos clases diferentes que tienen el mismo nombre. Por supuesto, en ese caso, que no se usará la directiva using o si lo hiciera tendría que especificar el espacio de nombres de las otras cosas en el espacio de nombres que quería.

Tenga en cuenta también que no necesita el uso de - que sólo puede utilizado std :: cout o lo que sea que necesite acceder. Usted Prefacio los artículos con el espacio de nombres.

Otros consejos

mediante directivas e incluyen las directivas de preprocesador son dos cosas diferentes. El include corresponde aproximadamente a la variable de entorno CLASSPATH de Java, o la opción -cp de la máquina virtual de Java.

Lo que hace es hacer los tipos conocidos por el compilador. Sólo <string> incluyendo, por ejemplo, le hará capaz de referirse a std::string:

#include <string>
#include <iostream>

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

Ahora, utilizando directivas son como import en Java. Hacen nombres visible en el ámbito en que aparecen en, por lo que no tiene que calificar totalmente ellos nunca más. Al igual que en Java, los nombres deben ser conocidos utilizados antes de que puedan hacerse visibles:

#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");
}

Es una mala práctica utilizar una directiva using en los archivos de cabecera, porque eso significa que cada otro archivo de origen que pasa a incluir verá los nombres usando búsqueda de nombre no calificado. A diferencia de Java, donde sólo hacer nombres visibles para el paquete de la línea de importación aparece en, En C ++ que puede afectar a todo el programa, si incluyen ese archivo de forma directa o indirecta.

Tenga cuidado al hacerlo en el ámbito global, incluso en los archivos de implementación. Mejor usarlos lo más local posible. Por espacio de nombres std, yo nunca uso ese. I, y muchas otras personas, simplemente Siempre escribo std:: delante de nombres. Pero si le toca hacerlo, hacerlo de esta manera:

#include <string>
#include <iostream>

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

Por lo que son espacios de nombres y por qué los necesita, por favor lea la propuesta Bjarne Stroustrup dio 1,993 para agregarlos a la próxima C ++ estándar. Está bien escrito:

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

En #include C ++ y usando tener diferentes funciones.

#include pone el texto del archivo incluido en el archivo de origen (en realidad ) , espacios de nombres, por otro lado son sólo un mecanismo para tener nombres únicos para que diferentes personas pueden crear un objeto "foo".

Esto viene de C ++ no tener el concepto de un módulo.

Tenga en cuenta que espacios de nombres en C ++ están abiertas, lo que significa que los diferentes archivos pueden definir diferentes partes de un mismo espacio de nombres (algo así como las clases parciales de .NET).

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

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

El incluyen es definir la existencia de las funciones.

El uso es lo que hace más fácil su uso.

cout como se define en iostream es en realidad el nombre "std :: cout".

Se puede evitar el uso del espacio de nombres por escrito.

std::cout << "Hello World";

Estas palabras clave se utilizan para diferentes propósitos.

El uso de palabras clave hace que un nombre de un espacio de nombres disponibles para su uso en la región declarativa actual. Su mayor parte por conveniencia para que usted no tiene que utilizar el nombre completo todo el tiempo. Este página lo explica con cierto detalle.

La instrucción # include es una directiva de procesador pre y le dice al preprocesador para tratar el contenido de un archivo especificado como si esos contenidos habían aparecido en el programa fuente en el punto donde se usa la directiva. Es decir, se puede pensar en esta declaración como copiar el archivo incluido en la actual. El compilador compila el archivo completo como si escribió todo el código en un archivo grande.

Creo que las otras respuestas no viene al caso ligeramente. En todos C ++, Java y C #, lo using / import es totalmente opcional. Así que no es diferente.

Y entonces usted tiene que hacer algo más para hacer que el código sea visible de todos modos, en las tres plataformas.

En C ++, mínimamente tiene que incluir en la unidad de traducción actual (lo suficientemente bueno para muchas implementaciones de vectores, hilo, etc.), a menudo hay que añadir algo a su enlazador también, aunque algunas bibliotecas hacen que automáticamente basado en el include (por ejemplo, en la construcción de impulso en Windows).

Y en C # hay que añadir una referencia a otro conjunto. Que se encarga del equivalente incluye y ajustes de enlace.

Y en Java que tiene que garantizar el código está en la ruta de clase, por ejemplo, añadiendo el frasco correspondiente a la misma.

Así que hay cosas muy estrechamente análogas requeridas en las tres plataformas, y la separación entre using / import (conveniencia) y la resolución de vinculación real (un requisito) es el mismo en los tres.

Como se señaló, C++ y Java son lenguajes diferentes y hacen cosas algo diferentes.Además, C++ es más un lenguaje "crecido en broma" y Java más un lenguaje diseñado.

Mientras using namespace std; No es necesariamente una mala idea, usarlo para todos los espacios de nombres eliminará todo el beneficio.Los espacios de nombres existen para que pueda escribir módulos sin tener en cuenta los conflictos de nombres con otros módulos, y using namespace this; using namespace that; puede crear ambigüedades.

Es necesario comprender espacios de nombres si se quiere entender realmente esto.

Con include que se acaba de incluir el archivo de cabecera.

Con using namespace está declarando que está utilizando un espacio de nombres dado que contiene cosas como cout. así que si usted hace esto:

using namespace std;

para que utilice cout que sólo puede hacer

cout << "Namespaces are good Fun";

en lugar de:

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

Tenga en cuenta que si no #include <iostream> usted no será capaz de utilizar ni std::cout ni cout en sus declaraciones y así sucesivamente, ya que no está incluido el encabezado.

Un forro (no es que esto es algo nuevo:)):

std le permite omitir el std :: prefijo, pero no se puede utilizar cout en absoluto sin iostream .

Incluso Stroustrup se refiere al mecanismo #include como algo hacker. Sin embargo sí hace mucho más fácil de compilación independiente (bibliotecas y cabeceras de buques compilado en lugar de todo el código fuente).

La pregunta realmente es "¿por qué C ++ - después de que ya tenía el mecanismo #include - añadir espacios de nombres"

El mejor ejemplo que conozco acerca de por qué no es suficiente #include proviene de Sun. Al parecer, los desarrolladores de Sun tenían algunos problemas con uno de sus productos, ya que habían escrito una función mktemp() que pasó a tener la misma firma en función mktemp() que fue incluida a través de un archivo que fue a su vez incluido a través de una cabecera del proyecto en realidad quería.

Por supuesto, las dos funciones no eran compatibles, y uno no podría ser utilizado como un sustituto de la otra. Por otra parte, el compilador y el enlazador no se dieron cuenta de esto cuando la construcción de la binaria, ya veces mktemp() llamarían una función, y en ocasiones sería llamar a otro, basado en los archivos de diferente orden fueron compilados o vinculados.

El problema se deriva del hecho de que C ++ fue originalmente compatible con - y esencialmente alcancía respaldados por encima de - C Y C sólo tiene un espacio de nombres global. C ++ resolvió este problema - en el código que no es compatible con C -. Través de espacios de nombres

C # y Java (1) tienen un mecanismo de espacio de nombres (namespace en C #, package en Java), (2) por lo general se desarrollan a través de entornos de desarrollo que manejan en referencia a los binarios para el desarrollador, y (3) no permiten independiente funciones (un ámbito de clase es algo así como un espacio de nombres, y reduce el riesgo de contaminar el espacio de nombres global) por lo que tienen una solución diferente a este problema. Sin embargo, todavía es posible tener cierta ambigüedad respecto a qué método que está llamando (por ejemplo, nombre de un choque entre dos interfaces que hereda una clase), y en ese caso los tres idiomas exigir al programador especificar claramente qué método son en realidad buscando, por lo general anteponiendo el nombre de la clase padre / interfaz.

En C ++, la directiva include se copia y pega el archivo de cabecera en el código fuente en el paso de procesamiento previo. Cabe señalar que un archivo de cabecera generalmente contiene funciones y clases declaradas dentro de un espacio de nombres. Por ejemplo, la cabecera <vector> podría ser similar a algo como esto:

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

Supongamos que es necesario definir un vector en su función principal, hacer #include <vector> y usted tiene el fragmento de código anterior en el código ahora:

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

Tenga en cuenta que en el código de la clase vector se encuentra todavía en el espacio de nombres std. Sin embargo, su función principal es en el espacio de nombres global por defecto, por lo que simplemente incluyendo la cabecera no hará que la clase vector de espacio de nombres visibles en global. Usted tiene que usar ya sea o no el prefijo using como std::vector.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top