Considere un par de dos archivos fuente: un archivo de declaración de interfaz ( *.h
o *.hpp
) y su archivo de implementación ( *.cpp
).
Deje que el *.h
archivo sea como el siguiente:
namespace MyNamespace {
class MyClass {
public:
int foo();
};
}
He visto dos prácticas diferentes para usar espacios de nombres en archivos fuente:
*.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: ¿Existen diferencias entre estas dos prácticas y se considera que una es mejor que la otra?
c++
namespaces
header-files
Nickolay
fuente
fuente
int MyNamespace::MyClass::foo() ...
.Respuestas:
Desde el punto de vista de la legibilidad del código, probablemente sea mejor, en mi opinión, usar el método # 2 por esta razón:
Puede haber
using
varios espacios de nombres a la vez, y cualquier objeto o función escrito debajo de esa línea puede pertenecer a cualquiera de esos espacios de nombres (salvo conflictos de nombres). Envolver todo el archivo en unnamespace
bloque es más explícito y le permite declarar nuevas funciones y variables que pertenecen a ese espacio de nombres dentro del archivo .cpp tambiénfuente
La más clara es la opción que no mostró:
int MyNamespace::MyClass::foo() { // ... }
También es muy detallado; demasiado para la mayoría de la gente. Dado que
using namespace
es una receta para los conflictos de nombres, al menos en mi experiencia, y debe evitarse, excepto en ámbitos y lugares muy limitados, generalmente uso su # 2.fuente
Si. # 1 y # 2 son ejemplos de una directiva using y una definición de espacio de nombres respectivamente. Son efectivamente iguales en este caso, pero tienen otras consecuencias. Por ejemplo, si introduce un nuevo identificador al lado
MyClass::foo
, tendrá un alcance diferente:# 1:
using namespace MyNamespace; int x; // defines ::x
# 2:
namespace MyNamespace { int x; // defines MyNamespace::x }
Pros # 1: un poco más conciso; más difícil introducir accidentalmente algo en
MyNamespace
sin saberlo. Contras: puede extraer identificadores existentes de forma involuntaria.# 2 Pros: es más claro que las definiciones de identificadores existentes y las declaraciones de identificadores nuevos pertenecen a ambas
MyNamespace
. Contras: es más fácil introducir identificadores de forma involuntariaMyNamespace
.Una crítica tanto del n. ° 1 como del n. ° 2 es que se refieren a un espacio de nombres completo cuando probablemente solo le interese la definición de miembros de
MyNamespace::MyClass
. Esto es torpe y comunica mal la intención.Una posible alternativa al n. ° 1 es una declaración de uso que incluye solo el identificador que le interesa:
#include "MyClass.h" using MyNamespace::MyClass; int MyClass::foo() { ... }
fuente
También me gustaría agregar que si, por alguna razón, decide implementar una especialización de plantilla en un archivo cpp y simplemente confía en
using namespace
que se encontrará con 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 aplica el método n. ° 2, estará bien.
fuente
Me gustaría agregar una forma más, usando using-statement :
#include "MyClass.h" using MyNamespace::MyClass; int MyClass::foo() { ... }
De esta manera, le ahorra escribir el nombre del espacio de nombres muchas veces si la clase tiene muchas funciones
fuente