Vengo de un fondo de Java, donde se usan paquetes, no espacios de nombres. Estoy acostumbrado a poner clases que funcionan juntas para formar un objeto completo en paquetes, y luego reutilizarlas más tarde de ese paquete. Pero ahora estoy trabajando en C ++.
¿Cómo se usan los espacios de nombres en C ++? ¿Crea un único espacio de nombres para toda la aplicación o crea espacios de nombres para los componentes principales? Si es así, ¿cómo se crean objetos a partir de clases en otros espacios de nombres?
fuente
std
espacio de nombres a los símbolos en lugar de usarlosusing
. Entonces siempre escribostd::cout
ostd::string
ahora porque así es como los llamo ahora. Nunca solo escribiríacout
.std
, personalmente he encontrado que esto es mucho menos importante cuando se trata de bibliotecas más pequeñas. A menudo solo puede usarusing namespace FooBario;
, especialmente si está utilizando una cantidad considerable de tipos de una biblioteca.using namespace X;
debe evitarse en los archivos de encabezado si es posible.mylibrary::endl
para representar mi propia secuencia especial de nueva línea. Quiero decir, ¿por qué inventar nombres?Para evitar decir todo, Mark Ingram ya dijo un pequeño consejo para usar espacios de nombres:
Evite la directiva "usar el espacio de nombres" en los archivos de encabezado; esto abre el espacio de nombres para todas las partes del programa que importan este archivo de encabezado. En los archivos de implementación (* .cpp) esto normalmente no es un gran problema, aunque prefiero usar la directiva "using namespace" en el nivel de función.
Creo que los espacios de nombres se utilizan principalmente para evitar conflictos de nombres, no necesariamente para organizar la estructura de su código. Organizaría programas C ++ principalmente con archivos de encabezado / estructura de archivos.
A veces, los espacios de nombres se utilizan en proyectos C ++ más grandes para ocultar detalles de implementación.
Nota adicional a la directiva de uso: Algunas personas prefieren usar "usar" solo para elementos individuales:
fuente
using std::cout;
es una declaración de usousing std::cout, std::endl;
o inclusousing std::cout, endl;
,.using namespace x
en un encabezado si está dentro de otro espacio de nombres. No es algo que recomendaría en general, pero no contamina el espacio de nombres global.Vincent Robert tiene razón en su comentario ¿Cómo se usan correctamente los espacios de nombres en C ++? .
Usando espacio de nombres
Los espacios de nombres se utilizan como mínimo para ayudar a evitar la colisión de nombres. En Java, esto se aplica a través del idioma "org.domain" (porque se supone que uno no usará nada más que su propio nombre de dominio).
En C ++, puede asignar un espacio de nombres a todo el código de su módulo. Por ejemplo, para un módulo MyModule.dll, puede asignar a su código el espacio de nombres MyModule. He visto en otra parte a alguien que usa MyCompany :: MyProject :: MyModule. Supongo que esto es excesivo, pero en general, me parece correcto.
Usar "usar"
El uso debe usarse con mucho cuidado porque importa efectivamente uno (o todos) los símbolos de un espacio de nombres a su espacio de nombres actual.
Es malo hacerlo en un archivo de encabezado porque su encabezado contaminará todas las fuentes incluidas (me recuerda a las macros ...), e incluso en un archivo de origen, mal estilo fuera del alcance de una función porque se importará a alcance global Los símbolos del espacio de nombres.
La forma más segura de usar "usar" es importar símbolos seleccionados:
Verá mucho "usar el espacio de nombres estándar"; en tutoriales o códigos de ejemplo. La razón es reducir la cantidad de símbolos para facilitar la lectura, no porque sea una buena idea.
"utilizando el espacio de nombres estándar;" Scott Meyers lo desalienta (no recuerdo exactamente qué libro, pero puedo encontrarlo si es necesario).
Composición del espacio de nombres
Los espacios de nombres son más que paquetes. Otro ejemplo se puede encontrar en "El lenguaje de programación C ++" de Bjarne Stroustrup.
En la "Edición especial", en 8.2.8 Composición del espacio de nombres , describe cómo puede combinar dos espacios de nombres AAA y BBB en otro llamado CCC. Por lo tanto, CCC se convierte en un alias para AAA y BBB:
Incluso podría importar símbolos seleccionados de diferentes espacios de nombres, para construir su propia interfaz de espacio de nombres personalizada. Todavía tengo que encontrar un uso práctico de esto, pero en teoría, es genial.
fuente
No vi ninguna mención de ello en las otras respuestas, así que aquí están mis 2 centavos canadienses:
En el tema "uso del espacio de nombres", una declaración útil es el alias del espacio de nombres, que le permite "renombrar" un espacio de nombres, normalmente para darle un nombre más corto. Por ejemplo, en lugar de:
puedes escribir:
fuente
No escuche a todas las personas que le dicen que los espacios de nombres son solo espacios de nombres.
Son importantes porque el compilador considera que aplican el principio de interfaz. Básicamente, se puede explicar con un ejemplo:
Si quisieras imprimir un objeto A, el código sería este:
Tenga en cuenta que no mencionamos explícitamente el espacio de nombres al llamar a la función. Este es el principio de la interfaz: C ++ considera una función que toma un tipo como argumento como parte de la interfaz para ese tipo, por lo que no es necesario especificar el espacio de nombres porque el parámetro ya implica el espacio de nombres.
Ahora, ¿por qué es importante este principio? Imagine que el autor de la clase A no proporcionó una función print () para esta clase. Tendrá que proporcionar uno usted mismo. Como es un buen programador, definirá esta función en su propio espacio de nombres, o tal vez en el espacio de nombres global.
Y su código puede comenzar a llamar a la función print (a) donde lo desee. Ahora imagine que años más tarde, el autor decide proporcionar una función print (), mejor que la suya porque conoce los aspectos internos de su clase y puede hacer una versión mejor que la suya.
Luego, los autores de C ++ decidieron que su versión de la función print () debería usarse en lugar de la proporcionada en otro espacio de nombres, para respetar el principio de la interfaz. Y que esta "actualización" de la función print () debería ser lo más fácil posible, lo que significa que no tendrá que cambiar cada llamada a la función print (). Es por eso que las "funciones de interfaz" (función en el mismo espacio de nombres que una clase) pueden llamarse sin especificar el espacio de nombres en C ++.
Y es por eso que debe considerar un espacio de nombres C ++ como una "interfaz" cuando usa uno y tenga en cuenta el principio de la interfaz.
Si desea una mejor explicación de este comportamiento, puede consultar el libro Exceptional C ++ de Herb Sutter
fuente
En realidad, boost utiliza toneladas de espacios de nombres, por lo general, cada parte de boost tiene su propio espacio de nombres para el funcionamiento interno y luego puede colocar solo la interfaz pública en el impulso de espacio de nombres de nivel superior.
Personalmente, creo que cuanto más grande se hace una base de código, los espacios de nombres más importantes se vuelven, incluso dentro de una sola aplicación (o biblioteca). En el trabajo colocamos cada módulo de nuestra aplicación en su propio espacio de nombres.
Otro uso (sin juego de palabras) de espacios de nombres que uso mucho es el espacio de nombres anónimo:
Esto es básicamente lo mismo que:
Sin embargo, el uso de un espacio de nombres anónimo (en lugar de estático) es la forma recomendada para que el código y los datos sean visibles solo dentro de la unidad de compilación actual en C ++.
fuente
const int CONSTANT = 42;
porque la constante de nivel superior en un ámbito de espacio de nombres ya implica una vinculación interna. Por lo tanto, no necesita el espacio de nombres anónimo en este caso.Además, tenga en cuenta que puede agregar a un espacio de nombres. Esto es más claro con un ejemplo, lo que quiero decir es que puedes tener:
en un archivo
square.h
yen un archivo
cube.h
. Esto define un único espacio de nombresMyNamespace
(es decir, puede definir un único espacio de nombres en varios archivos).fuente
En Java:
En C ++:
Y usándolos, Java:
Y C ++:
Además, los nombres completos son "somepackge.SomeClass" para Java y "somenamespace :: SomeClass" para C ++. Con esas convenciones, puede organizarse como está acostumbrado en Java, incluida la creación de nombres de carpetas coincidentes para espacios de nombres. Sin embargo, los requisitos de carpeta-> paquete y archivo-> clase no están allí, por lo que puede nombrar sus carpetas y clases independientemente de los paquetes y espacios de nombres.
fuente
@ marius
Sí, puede usar varios espacios de nombres a la vez, por ejemplo:
[Feb. 2014 - (¿Realmente ha pasado tanto tiempo?): Este ejemplo en particular ahora es ambiguo, como señala Joey a continuación. Boost y std :: ahora cada uno tiene un shared_ptr.]
fuente
std
también tieneshared_ptr
por ahora, por lo tanto el usoboost
ystd
espacios de nombres chocará cuando intenta utilizar unashared_ptr
.También puede contener "usando el espacio de nombres ..." dentro de una función, por ejemplo:
fuente
En términos generales, creo un espacio de nombres para un cuerpo de código si creo que posiblemente haya conflictos de nombre de función o tipo con otras bibliotecas. También ayuda al código de marca, ala boost :: .
fuente
Prefiero usar un espacio de nombres de nivel superior para la aplicación y espacios de nombres secundarios para los componentes.
La forma en que puede usar las clases de otros espacios de nombres es sorprendentemente muy similar a la de Java. Puede usar "use NAMESPACE", que es similar a una instrucción "import PACKAGE", por ejemplo, use std. O puede especificar el paquete como prefijo de la clase separada con "::", por ejemplo, std :: string. Esto es similar a "java.lang.String" en Java.
fuente
Tenga en cuenta que un espacio de nombres en C ++ realmente es solo un espacio de nombres. No proporcionan nada de la encapsulación que hacen los paquetes en Java, por lo que probablemente no los usará tanto.
fuente
He usado espacios de nombres de C ++ de la misma manera que lo hago en C #, Perl, etc. Es solo una separación semántica de símbolos entre material de biblioteca estándar, material de terceros y mi propio código. Colocaría mi propia aplicación en un espacio de nombres, luego un componente de biblioteca reutilizable en otro espacio de nombres para la separación.
fuente
Otra diferencia entre java y C ++ es que en C ++, la jerarquía del espacio de nombres no necesita maquinar el diseño del sistema de archivos. Así que tiendo a colocar una biblioteca reutilizable completa en un solo espacio de nombres y subsistemas dentro de la biblioteca en subdirectorios:
Solo pondría los subsistemas en espacios de nombres anidados si existiera la posibilidad de un conflicto de nombres.
fuente