Yo vengo de una Java de fondo, donde los paquetes se usan, no los espacios de nombres. Estoy acostumbrada a poner las clases que trabajan juntos para formar un objeto completo dentro de los paquetes, y luego usarlos más tarde a partir de ese paquete. Pero ahora estoy trabajando en C++.

¿Cómo utilizar espacios de nombres en C++? Crear un espacio de nombres único para toda la aplicación, o crear espacios de nombres para los componentes principales? Si es así, ¿cómo se puede crear objetos a partir de clases en otros espacios de nombres?

InformationsquelleAutor Marius | 2008-09-03

15 Comentarios

  1. 163

    Espacios de nombres son los paquetes esencialmente. Que puede ser utilizado como esta:

    namespace MyNamespace
    {
      class MyClass
      {
      };
    }

    A continuación, en el código:

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

    Espero que ayude.

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

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

    Edición: Siguiente lo bernhardrusch ha dicho, tiendo a no utilizar el «using namespace x» de la sintaxis, no me suele especificar explícitamente el espacio de nombres al crear instancias de mis objetos (es decir, el primer ejemplo que se me mostró).

    Y como usted lo pidió a continuación, se puede utilizar como número de espacios de nombres como desee.

    • La OMI es mejor acostumbrarse a prefijando el std espacio de nombres de símbolos en lugar de utilizar using a todos. Así que yo siempre escribo std::cout o std::string ahora, porque eso es lo que yo llamo ahora. Yo nunca acaba de escribir cout.
    • Mientras que esto es muy cierto para std, personalmente, he encontrado esta mucho menos importante cuando usted está tratando con las bibliotecas más pequeñas. A menudo usted puede usar using namespace FooBario;, especialmente si usted está utilizando un número considerable de tipos a partir de una biblioteca.
    • Veo tu punto, pero no estoy de acuerdo porque las colisiones de nombres son (en mi mente) más probable que venga precisamente de una de esas pequeñas bibliotecas. La mayoría de la gente tiene cuidado de no llamar a las clases/funciones de los mismos en STL. Dicho esto, estoy de acuerdo en que using namespace X; debe ser evitado en los archivos de cabecera, si es posible.
    • gente tengan cuidado de no llamar a las clases/funciones de los mismos en STL» – que NO es TAN CIERTO. Por ejemplo, si yo fuera a escribir algunos muy especializados de e/S código por alguna extraña de hardware, yo nunca, nunca, usar otra cosa que mylibrary::endl para la representación de mi muy especial newline secuencia. Quiero decir, ¿por qué inventar nombres?
    • Mi compilador todavía no reconocer el espacio de nombres, aunque quiero especificar de forma explícita y me incluir el archivo donde se declara.
    • He visto a alguien usar: espacio de nombres someNamespace { class Miclase; } y, a continuación, definir: clase someNamespace::MyClass : público otherClass { // habitual de la clase de cosas } ¿Cuál es el propósito de poner Miclase con el espacio de nombres en la parte superior de un encabezado?

  2. 114

    Para evitar decir todo lo que Mark Ingram ya dijo un poco la punta para el uso de espacios de nombres:

    Evitar el «uso de espacio de nombres» de la directiva en los archivos de encabezado – de esta forma se abre el espacio de nombres para todas las partes del programa que importar este archivo de encabezado. En la aplicación los archivos (*.cpp) esto normalmente no es gran problema – aunque yo prefiero usar el «uso de espacio de nombres» directiva sobre el nivel de función.

    Creo que los espacios de nombres que se usan generalmente para evitar conflictos de nombres – no necesariamente para organizar su estructura de código. Me gustaría organizar los programas de C++ principalmente con archivos de encabezado /la estructura de archivos.

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

    Nota adicional para el uso de la directiva:
    Algunas personas prefieren utilizar el «uso» sólo para elementos individuales:

    using std::cout;  
    using std::endl;
    • Una de las ventajas de «uso de espacio de nombres» en el nivel de función como usted sugiere, en lugar de en los .archivo cpp nivel o espacio de nombres {} a nivel de bloque dentro de la .cpp es que ayuda en gran medida con una sola compilación-unidad fortalece. «using namespace» es transitiva, y se aplica para el espacio de nombres a través de Un discreto espacio de nombres de Un {} los bloques en la misma unidad, por lo que para una sola compilación de la unidad se construye rápidamente acabar con todo si se realiza en el archivo o el espacio de nombres a nivel de bloque.
    • using std::cout; es un uso de la declaración de
    • Es posible el uso de varios los nombres de una solo espacio de nombres en una sola instrucción? Algo así como using std::cout, std::endl; o incluso, using std::cout, endl; .
    • Se puede aceptar el uso de una using namespace x en un encabezado de si es dentro de otro espacio de nombres. No es algo que yo recomendaría en general, pero que no contamina el espacio de nombres global.
  3. 77

    Vincent Robert es el derecho en su comentario ¿Cómo utilizar correctamente los espacios de nombres en C++?.

    El uso de espacio de nombres

    Espacios de nombres se utilizan, al menos, para ayudar a evitar la colisión de nombres. En Java, esto es forzada a través de la «org.dominio de idioma (porque se supone que uno no uso otra cosa que su propio nombre de dominio).

    En C++, usted podría dar un espacio de nombres para todo el código en el módulo. Por ejemplo, para un módulo de MyModule.dll usted podría dar su código en el espacio de nombres MyModule. Yo he visto en otros lugares a alguien con Miempresa::Miproyecto::MyModule. Supongo que esto es una exageración, pero a pesar de todo, parece correcto para mí.

    El uso de «uso»

    A utilizar debe ser utilizada con mucho cuidado, ya que efectivamente la importación de uno (o todos) los símbolos de un espacio de nombres en el espacio de nombres actual.

    Esto es malo hacerlo en un archivo de cabecera porque el encabezado va a contaminar cada fuente, incluyendo (que me recuerda a la de macros…), e incluso en un archivo de código fuente, estilo malo fuera del ámbito de una función porque va a importar en el ámbito global de los símbolos del espacio de nombres.

    La forma más segura de utilizar el «uso» es la importación de seleccionar los símbolos:

    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 ;
    }

    Usted verá un montón de «using namespace std ;» en el tutorial o ejemplo de los códigos. La razón es reducir el número de símbolos para hacer la lectura más fácil, ya que no es una buena idea.

    «using namespace std ;» es desalentado por Scott Meyers (no recuerdo exactamente en qué libro, pero la puedo encontrar, si es necesario).

    Espacio De Nombres Composición

    Espacios de nombres son más que paquetes. Otro ejemplo puede encontrarse en Bjarne Stroustrup «El Lenguaje de Programación C++».

    En la «Edición Especial», en 8.2.8 espacio de Nombres Composición, él describe cómo se pueden fusionar dos espacios de nombres AAA y BBB en otra que se llama CCC. Por lo tanto CCC se convierte en un alias para ambos 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() ;
    }

    Usted puede incluso importar símbolos de diferentes espacios de nombres, para construir su propio espacio de nombres personalizado de la interfaz. Todavía tengo que encontrar un uso práctico de este, pero, en teoría, es genial.

    • Podrías aclarar, por favor «dar un espacio de nombres para todo el código en el módulo»? ¿Qué es una buena práctica para encapsular el módulo. Por ejemplo yo tengo la clase de números complejos y funciones externas relacionadas con los números complejos. Esta clase y esas dos funciones debe estar en un espacio de nombres?
  4. 71

    Yo no veo ninguna mención de él en las otras respuestas, así que aquí están mis 2 centavos de dólar Canadiense:

    Sobre el «uso de espacio de nombres» tema, un útil declaración es el espacio de nombres de alias, que permite «cambiar el nombre de» 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;

    se puede escribir:

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

    No escuchar a todas las personas diciendo que los espacios de nombres son sólo el nombre de los espacios.

    Son importantes debido a que son considerados por el compilador para aplicar la interfaz principio. Básicamente, se puede explicar mediante un ejemplo:

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

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

    ns::A a;
    print(a);

    Tenga en cuenta que nosotros no menciona explícitamente el espacio de nombres cuando se llama a la función. Esta es la interfaz de principio: C++ considerar una función que recibe un tipo de un argumento como parte de la interfaz de ese tipo, así que no hay necesidad de especificar el espacio de nombres debido a que el parámetro ya implícita en el espacio de nombres.

    Ahora, ¿por qué este principio es importante? Imagino que la clase de Un autor no proporciona la función print() de esta clase. Usted tendrá que proporcionar uno a sí mismo. Como eres un buen programador, va a 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 impresión(a) función de dondequiera que usted desee. Ahora imaginar que años más tarde, el autor decide proporcionar la función print (), mejor que la suya, porque él conoce las interioridades de su clase y puede hacer una mejor versión que la tuya.

    Luego C++ autores decidieron que su versión de la función print() debe ser utilizado en lugar de la establecida en otro espacio de nombres, a respetar la interfaz principio. Y que esta «actualización» de la función print() debería ser tan fácil como sea posible, lo que significa que usted no tendrá que cambiar cada vez que se llame a la función print (). Es por eso que «las funciones de interfaz» (función en el mismo espacio de nombres de la clase) puede ser llamado sin especificar el espacio de nombres en C++.

    Y es por eso que usted debe considerar un C++ espacio de nombres como una «interfaz» cuando se usa uno y tener en cuenta la interfaz de principio.

    Si quieres una mejor explicación de este comportamiento, puede consultar el libro Excepcional C++ de Herb Sutter

    • Usted realmente tiene que cambiar cada llamada a print() si ns::Imprimir se añade, sino que el compilador de la bandera de cada llamada como ambigua. En silencio el cambio a la nueva función sería una idea terrible.
    • Me pregunto ahora, después de lo @Vicente han dicho que va a tener que cambiar todas las llamadas a imprimir, si el autor proporcionaría ns::Imprimir() función, ¿qué estaba tratando de decir? Que cuando el autor añadió un ns::Imprimir() función, solo tienes que quitar tu propia aplicación? O que wuill acaba de agregar el uso de ns::imprimir() mediante la declaración? O domething más? Gracias
  6. 36

    Grandes proyectos de C++ he visto prácticamente no se utiliza más de un espacio de nombres (por ejemplo, impulso de la biblioteca).

    Realmente reforzar los usos de toneladas de espacios de nombres, normalmente cada parte de boost tiene su propio espacio de nombres para el funcionamiento interno y, a continuación, puede poner sólo la interfaz pública en el nivel superior del espacio de nombres de impulso.

    Personalmente creo que la más grande es una base de código se convierte en el más importante de los espacios de nombres se convierten, incluso dentro de una sola aplicación (o biblioteca). En el trabajo nos ha puesto a cada módulo de la aplicación en su propio espacio de nombres.

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

    namespace {
      const int CONSTANT = 42;
    }

    Este es básicamente el mismo como:

    static const int CONSTANT = 42;

    El uso de un anónimo espacio de nombres (en lugar de estático) es, sin embargo, la forma recomendada para el código y los datos a ser visible sólo dentro de la actual unidad de compilación en C++.

    • Ambos ejemplos son equivalentes a const int CONSTANT = 42; porque el nivel superior const en un ámbito de espacio de nombres ya implica vinculación interna. Así que usted no necesita el espacio de nombres anónimos en este caso.
  7. 18

    También, 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 usted puede 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 espacio de nombres único MyNamespace (es decir, se puede definir un espacio de nombres único a través de múltiples archivos).

  8. 11

    En Java:

    package somepackage;
    class SomeClass {}

    En C++:

    namespace somenamespace {
        class SomeClass {}
    }

    Y el uso de ellos, Java:

    import somepackage;

    Y C++:

    using namespace somenamespace;

    También, los nombres completos son «somepackge.SomeClass» para Java y «somenamespace::SomeClass» para C++. Mediante estos convenios, se puede organizar como usted está acostumbrado en Java, incluyendo la realización de la coincidencia de los nombres de carpeta para los espacios de nombres. La carpeta->paquete y el archivo->los requisitos de clase no están allí, así que usted puede poner el nombre a las carpetas y las clases de forma independiente fuera de los paquetes y espacios de nombres.

  9. 5

    Puede contener también «uso de espacio de nombres …» dentro de una función, por ejemplo:

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

    @marius

    Sí, usted puede utilizar varios espacios de nombres en un tiempo, 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

    [Febrero. 2014 — (¿Ha sido realmente que largo?): Este ejemplo en particular es ahora ambiguo, ya que Joey se señala a continuación. Impulsar y std:: ahora cada uno tiene un shared_ptr.]

    • Tenga en cuenta que std también ha shared_ptr por ahora, por lo que el uso de ambos boost y std espacios de nombres se chocan cuando intenta utilizar un shared_ptr.
    • Este es un buen ejemplo de por qué muchas casas de software va a desalentar la importación de toda espacios de nombres en este camino. No duele para siempre especificar el espacio de nombres, y si es demasiado largo, a continuación, hacer un alias o sólo importante de las clases del espacio de nombres.
  11. 3

    Generalmente hablando, puedo crear un espacio de nombres para un cuerpo de código si yo creo que no podría ser, posiblemente, la función o el nombre del tipo de conflictos con otras bibliotecas. También ayuda a código de marca, ala boost:: .

  12. 3

    Yo prefiero usar un nivel superior del espacio de nombres de la aplicación y sub espacios de nombres para los componentes.

    La forma en que usted puede utilizar las clases de otros espacios de nombres es, sorprendentemente, muy similar a la forma en java.
    Usted puede utilizar el «uso de espacio de NOMBRES», que es similar a una «importación» PAQUETE de instrucción, por ejemplo, el uso de las ets. O especificar el paquete como prefijo de la clase separados por «::», por ejemplo, std::string. Esto es similar a «de java.lang.Cadena» en Java.

  13. 3

    Tenga en cuenta que un espacio de nombres en C++ en realidad es sólo un espacio de nombre. Ellos no proporcionan ninguna de la encapsulación de los paquetes hacerlo en Java, por lo que probablemente no va a hacer uso de ellos.

  14. 2

    He usado C++ espacios de nombres de la misma manera en que lo hago en C#, Perl, etc. Es sólo una semántica de la separación de los símbolos entre los de la biblioteca estándar de cosas, de terceros cosas, y mi propio código. Me gustaría poner mi propia app en un espacio de nombres, a continuación, una biblioteca reutilizable componente en otro espacio de nombres para la separación.

  15. 2

    Otra diferencia entre java y C++, es que en C++, la jerarquía del espacio de nombres no necesita de mach a la disposición de archivos. Por lo que tienden a poner toda una biblioteca reutilizable en un único espacio de nombres, y de los subsistemas dentro de la biblioteca en subdirectorios:

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

    Sólo quiero poner de los subsistemas en los espacios de nombres anidados si existía la posibilidad de un conflicto de nombres.

Dejar respuesta

Please enter your comment!
Please enter your name here