tipos sintaxis programar funciones ejemplos dev datos como comandos codigos basicos c++ namespaces

programar - sintaxis de c++



¿Cómo usas correctamente los espacios de nombres en C++? (15)

Vengo de un fondo de Java, donde se usan paquetes, no espacios de nombres. Estoy acostumbrado a poner clases que trabajan juntas para formar un objeto completo en paquetes, y luego reutilizarlos después 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 crea objetos a partir de clases en otros espacios de nombres?


Los proyectos de C ++ más grandes que apenas he visto utilizan más de un espacio de nombres (por ejemplo, la biblioteca boost).

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 aumento de espacio de nombres de nivel superior.

Personalmente creo que cuanto más grande se vuelve una base de código, más importantes son los espacios de nombres, incluso dentro de una sola aplicación (o biblioteca). En el trabajo ponemos cada módulo de nuestra aplicación en su propio espacio de nombres.

Otro uso (sin juego de palabras) de los espacios de nombres que uso mucho es el espacio de nombres anónimo:

namespace { const int CONSTANT = 42; }

Esto es básicamente lo mismo que:

static const int CONSTANT = 42;

Sin embargo, usar 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 ++.


@ below

Sí, puedes usar varios espacios de nombres a la vez, por ejemplo:

using namespace boost; using namespace std; shared_ptr<int> p(new int(1)); // shared_ptr belongs to boost cout << "cout belongs to std::" << endl; // cout and endl are in std

[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.]


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:

namespace MyNamespace { double square(double x) { return x * x; } }

en un archivo square.h , y

namespace MyNamespace { double cube(double x) { return x * x * x; } }

en un archivo cube.h Esto define un solo espacio de nombres MyNamespace (es decir, puede definir un solo espacio de nombres en varios archivos).


En Java:

package somepackage; class SomeClass {}

En C ++:

namespace somenamespace { class SomeClass {} }

Y usándolos, Java:

import somepackage;

Y C ++:

using namespace somenamespace;

Además, los nombres completos son "somepackge.SomeClass" para Java y "somenamespace :: SomeClass" para C ++. Usando esas convenciones, puede organizar como está acostumbrado en Java, incluyendo hacer coincidir los nombres de las carpetas para los espacios de nombres. Sin embargo, los requisitos de carpeta-> paquete y archivo-> clase no están allí, por lo que puede asignar un nombre a sus carpetas y clases independientemente de los paquetes y espacios de nombres.


En términos generales, creo un espacio de nombres para un cuerpo de código si creo que posiblemente haya conflictos de función o de tipo con otras bibliotecas. También ayuda al código de marca, ala boost:: .


He usado los espacios de nombres de C ++ de la misma forma que lo hago en C #, Perl, etc. Es solo una separación semántica de símbolos entre las cosas de la biblioteca estándar, las cosas 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.


Los espacios de nombres son esencialmente paquetes. Se pueden usar así:

namespace MyNamespace { class MyClass { }; }

Luego en el código:

MyNamespace::MyClass* pClass = new MyNamespace::MyClass();

Espero que ayude.

O, si desea usar siempre un espacio de nombres específico, puede hacer esto:

using namespace MyNamespace; MyClass* pClass = new MyClass();

Edición: siguiendo lo que ha dicho bernhardrusch , tiendo a no usar la sintaxis de "usar espacio de nombres x", por lo general especifico explícitamente el espacio de nombres al crear una instancia de mis objetos (es decir, el primer ejemplo que mostré).

Y como lo pidió a below , puede usar tantos espacios de nombres como desee.


No escuches a todas las personas que te dicen que los espacios de nombres son solo espacios de nombres.

Son importantes porque el compilador los considera para aplicar el principio de interfaz. Básicamente, se puede explicar con un ejemplo:

namespace ns { class A { }; void print(A a) { } }

Si desea imprimir un objeto A, el código sería este:

ns::A a; print(a);

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 que una función 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 implicaba el espacio de nombres.

Ahora ¿por qué este principio es importante? Imagine que el autor de la clase A no proporcionó una función print () para esta clase. Usted tendrá que proporcionar uno mismo. Como usted es un buen programador, definirá esta función en su propio espacio de nombres, o tal vez en el espacio de nombres global.

namespace ns { class A { }; } void print(A a) { }

Y su código puede comenzar a llamar a la función de impresión (a) donde lo desee. Ahora imagine que años más tarde, el autor decide proporcionar una función de impresión (), 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 () se debería usar en lugar de la que se proporciona en otro espacio de nombres, para respetar el principio de interfaz. Y que esta "actualización" de la función de impresión () debería ser lo más fácil posible, lo que significa que no tendrá que cambiar cada llamada a la función de impresión (). Es por eso que se pueden llamar "funciones de interfaz" (función en el mismo espacio de nombres que una clase) sin especificar el espacio de nombres en C ++.

Y es por eso que debe considerar un espacio de nombres de C ++ como una "interfaz" cuando usa uno y tener 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


No vi ninguna mención al respecto en las otras respuestas, así que aquí están mis 2 centavos canadienses:

En el tema "usar espacio de nombres", una declaración útil es el alias de espacio de nombres, que le permite "renombrar" un espacio de nombres, normalmente para darle un nombre más corto. Por ejemplo, en lugar de:

Some::Impossibly::Annoyingly::Long:Name::For::Namespace::Finally::TheClassName foo; Some::Impossibly::Annoyingly::Long:Name::For::Namespace::Finally::AnotherClassName bar;

puedes escribir:

namespace Shorter = Some::Impossibly::Annoyingly::Long:Name::For::Namespace::Finally; Shorter::TheClassName foo; Shorter::AnotherClassName bar;


Otra diferencia entre java y C ++, es que en C ++, la jerarquía de espacio de nombres no necesita mecanizar 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:

#include "lib/module1.h" #include "lib/module2.h" lib::class1 *v = new lib::class1();

Solo pondría los subsistemas en espacios de nombres anidados si existiera la posibilidad de un conflicto de nombres.


Para evitar decir todo, Mark Ingram ya dijo un pequeño consejo para usar los espacios de nombres:

Evite la directiva "usar 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 "usar espacio de nombres" en el nivel de función.

Creo que los espacios de nombres se usan principalmente para evitar conflictos de nombres, no necesariamente para organizar la estructura de su código. Organizaba programas en C ++ principalmente con archivos de cabecera / la estructura de archivos.

A veces, los espacios de nombres se utilizan en proyectos de C ++ más grandes para ocultar los detalles de la implementación.

Nota adicional a la directiva de uso: algunas personas prefieren usar "usar" solo para elementos individuales:

using std::cout; using std::endl;


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 puedes usar clases de otros espacios de nombres es sorprendentemente muy similar a la forma en java. Puede usar "use NAMESPACE" que es similar a una declaración "import PACKAGE", por ejemplo, use std. O bien, especifique el paquete como prefijo de la clase separada con "::", por ejemplo, std :: string. Esto es similar a "java.lang.String" en Java.


También puede contener "usar espacio de nombres ..." dentro de una función, por ejemplo:

void test(const std::string& s) { using namespace std; cout << s; }


Tenga en cuenta que un espacio de nombres en C ++ realmente es solo un espacio de nombres. No proporcionan ninguna de la encapsulación que hacen los paquetes en Java, por lo que probablemente no los usará tanto.


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 al menos 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, podría asignar a su código el espacio de nombres MyModule. He visto a alguien usando MyCompany :: MyProject :: MyModule. Supongo que esto es una exageración, pero en general, me parece correcto.

Usando "usando"

El uso se debe usar con mucho cuidado, ya que efectivamente importa uno (o todos) los símbolos de un espacio de nombres a su espacio de nombres actual.

Esto es malo hacerlo en un archivo de encabezado porque su encabezado contaminará todas las fuentes que lo incluyan (me recuerda a las macros ...), e incluso en un archivo de origen, un estilo incorrecto fuera del ámbito de la función porque se importará en el ámbito global Los símbolos del espacio de nombres.

La forma más segura de usar "usar" es importar símbolos seleccionados:

void doSomething() { using std::string ; // string is now "imported", at least, // until the end of the function string a("Hello World!") ; std::cout << a << std::endl ; } void doSomethingElse() { using namespace std ; // everything from std is now "imported", at least, // until the end of the function string a("Hello World!") ; cout << a << endl ; }

Verás un montón de "using namespace std;" En tutoriales o códigos de ejemplo. La razón es reducir el número de símbolos para facilitar la lectura, no porque sea una buena idea.

"usando namespace std;" está desanimado por Scott Meyers (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 se pueden combinar dos espacios de nombres AAA y BBB en otro llamado CCC. Así CCC se convierte en un alias para AAA y BBB:

namespace AAA { void doSomething() ; } namespace BBB { void doSomethingElse() ; } namespace CCC { using namespace AAA ; using namespace BBB ; } void doSomethingAgain() { CCC::doSomething() ; CCC::doSomethingElse() ; }

Incluso podría importar símbolos seleccionados desde diferentes espacios de nombres, para crear 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.