2012-05-30 11 views
54

Considere un par de dos archivos de origen: un archivo de declaración de interfaz (*.h o *.hpp) y su archivo de implementación (*.cpp).C++: espacios de nombres: ¿cómo usarlos correctamente en los archivos de encabezado y fuente?

permiten que el archivo *.h ser como la siguiente:

namespace MyNamespace { 
    class MyClass { 
    public: 
    int foo(); 
    }; 
} 

he visto dos prácticas diferentes para usar espacios de nombres de archivos de origen:

*.cpp mostrando la práctica # 1:

#include "MyClass.h" 
using namespace MyNamespace; 

int MyClass::foo() { ... } 

*.cpp mostrando la práctica # 2:

#include "MyClass.h" 
namespace MyNamespace { 

    int MyClass::foo() { ... } 

} 

Mi pregunta: ¿Hay alguna diferencia entre estas dos prácticas y se considera una mejor que la otra?

+23

También hay la opción 3 : Solo nosotros el nombre completo, por ejemplo 'int MyNamespace :: MyClass :: foo() ...'. –

+1

Posible duplicado: http://stackoverflow.com/questions/7789163/using-directive-best-practice – David

+0

@Dave no duplicado. Estas preguntas se complementan entre sí. Recomiende agregar el enlace provisto por Dave como "Lea también ..." a esta pregunta. Mi pregunta ayudará a los principiantes a elegir el estilo correcto. – DaddyM

Respuesta

42

Desde un punto de vista de la legibilidad del código, es probablemente mejor en mi opinión a utilizar el método # 2 por esta razón:

Usted puede haber using varios espacios de nombres a la vez, y cualquier objeto o función escrita por debajo de la línea de puede pertenecer a cualquiera de esos espacios de nombres (salvo conflictos de nombres). Envolviendo todo el archivo en un bloque namespace es más explícito, y le permite declarar nuevas funciones y variables que pertenecen a ese espacio de nombres en el archivo .cpp, así

+0

Gracias. Muy claro. Esperará un poco para obtener otras respuestas. – DaddyM

+0

La pregunta que Dave relacionó en su comentario con su pregunta también describe algunos puntos clave en las diferencias (si las hay) entre los dos métodos que está buscando en –

+0

Chicos, realmente no sé de quién es la respuesta para seleccionar. Tienen intersección y se complementan entre sí. – DaddyM

36

El más claro es la opción que no mostraron:

int MyNamespace::MyClass::foo() 
{ 
    // ... 
} 

También es muy detallado; demasiado para la mayoría de las personas. Dado que using namespace es un recepe para conflictos de nombres, al menos en mi experiencia, y debe evitarse excepto en ámbitos y lugares muy limitados, I generalmente usa su # 2.

+2

Gracias muy claro. Juntos, hicimos una buena página de preguntas frecuentes para usuarios de espacios de nombres. :) – DaddyM

+0

Chicos, realmente no sé de quién es la respuesta para seleccionar. Tienen intersección y se complementan entre sí. – DaddyM

4

¿Hay alguna diferencia entre estas dos prácticas

Sí. # 1 y # 2 son ejemplos de using-directive y namespace definition respectivamente. Son efectivamente lo mismo en este caso, pero tienen otras consecuencias. Por ejemplo, si se introduce un nuevo identificador junto MyClass::foo, tendrá un alcance diferente:

# 1:

using namespace MyNamespace; 
int x; // defines ::x 

# 2:

namespace MyNamespace { 
    int x; // defines MyNamespace::x 
} 

es uno considera mejor que ¿el otro?

# 1 Ventajas: un poco más escueto; más difícil de introducir accidentalmente algo en MyNamespace involuntariamente. Contras: puede tirar identificadores existentes involuntariamente.

# 2 Pros: es más claro que las definiciones de los identificadores existentes y las declaraciones de los nuevos identificadores pertenecen a MyNamespace. Contras: es más fácil introducir involuntariamente identificadores en MyNamespace.

Una crítica de ambos # 1 y # 2 es que se están refiriendo a un espacio de nombre completo cuando probablemente solo le importe la definición de miembros de MyNamespace::MyClass. Esto es mano dura y comunica la intención pobremente.

Una posible alternativa a # 1 es un using-declaration que incluye sólo el identificador que le interesa:

#include "MyClass.h" 
using MyNamespace::MyClass; 

int MyClass::foo() { ... } 
2

Me gustaría también añadir que si se decide debido a alguna razón para poner en práctica una plantilla especialización en un archivo CPP y sólo se basan en using namespace que se ejecutará en el siguiente problema:

// .h file 
namespace someNameSpace 
{ 
    template<typename T> 
    class Demo 
    { 
     void foo(); 
    }; 
} 

// .cpp file 
using namespace someNameSpace; 

template<typename T> 
void Demo<T>::foo(){} 

// this will produce 
// error: specialization of 'template<class T> void someNameSpace::Demo<T>::foo()' in different namespace [-fpermissive] 
template<> 
void Demo<int>::foo(){} 

de lo contrario si se aplica el método # 2 esta va a estar bien.

0

Me gustaría añadir una manera mucho más utilizando usando-declaración:

#include "MyClass.h" 
using MyNamespace::MyClass; 

int MyClass::foo() { ... } 

De esta manera se salva de escribir el nombre del espacio de nombres muchas veces si la clase tiene muchas funciones

Cuestiones relacionadas