c++ - que - using namespace c#
¿Cuál es el propósito de: "usar espacio de nombres"? (6)
"Los espacios de nombres permiten agrupar entidades como clases, objetos y funciones bajo un nombre. De esta manera, el alcance global puede dividirse en" sub-ámbitos ", cada uno con su propio nombre. Donde identificador es cualquier identificador válido y las entidades son el conjunto de Clases, objetos y funciones que se incluyen dentro del espacio de nombres "
Más información aquí: http://www.cplusplus.com/doc/tutorial/namespaces/
Hay argumentos convincentes en against using namespace std
, así que ¿por qué se introdujo en el lenguaje? ¿ using namespace
el espacio de nombres no using namespace
el propósito de los espacios de nombres? ¿Por qué querría escribir using namespace
? ¿Hay algún problema que no conozca que se resuelva de manera elegante mediante el using namespace
, tal vez en las líneas del using std::swap
o algo por el estilo?
La gente se opone específicamente al using namespace std;
pero no para using namespace BigCorp
; o para referirse a std::cout
(que está usando el espacio de nombres, simplemente no lo está using
, si sabe a qué me refiero). Además, la mayoría de las objeciones al using namespace std
están en un archivo de encabezado. En un archivo fuente, donde los efectos se pueden ver de inmediato, es menos dañino.
Los espacios de nombres son un concepto increíblemente útil que me permite tener una clase llamada Fecha, aunque una biblioteca que estoy usando tiene una clase llamada Fecha. Antes de que se agregaran al idioma, teníamos que tener cosas como GCDate
y GCString
(mi compañía, Gregory Consulting, es anterior a std::string
). El uso de espacios de nombres (con o sin using
palabra clave) nos permite a todos escribir código más limpio y mejor. Pero cuando tienes que decir Gregcons::string
cada vez, pierdes la parte más limpia y nítida. [Descargo de responsabilidad: en realidad ya no uso mi propia clase de cadena: imagine algún conflicto de nombre apropiado.] Ese es el atractivo de la declaración de using
. Manténgalo alejado de los encabezados, no lo aplique a la std
, y por lo general debe mantenerse fuera de problemas.
La mayoría de las veces es solo un atajo para escribir código. Puedes importar nombres a tu contexto de encierro. Generalmente lo .cpp
archivos .cpp
, porque cuando incluyes una directiva using en un archivo .h
, contamina todos los archivos en los que está incluido. Otra buena práctica es restringir el using namespace
de using namespace
al entorno más envolvente posible, por ejemplo, dentro de una declaración del cuerpo del método. Lo veo como una conveniencia, no más, y similar al aliasing de espacio de nombres, como:
namespace po = boost::program_options;
y luego puedes escribir
po::variables_map ...
La razón principal por la que se introdujo el using namespace
fue la compatibilidad con versiones anteriores: si tiene muchos códigos de espacio de nombres previos que utilizan muchas funciones y clases de biblioteca estándar (versiones pre-estándar), desea una manera sencilla de hacer que ese código funcione con un estándar compilador conforme.
Por cierto, las reglas de búsqueda dependientes del argumento, al menos para C ++ 98, significan que el using namespace std::rel_ops
no hará lo que se desea en las plantillas (no sé si esto cambió en una versión posterior del estándar).
Ejemplo:
template<typename T> bool bar(T t)
{
return t > T();
}
namespace foo
{
class X {};
bool operator<(X, X);
}
using namespace std::rel_ops;
int main()
{
X x;
bar(x); // won''t work: X does not have operator>
}
Tenga en cuenta que poner el using namespace
de namespace foo
using namespace
en el namespace foo
de namespace foo
tampoco ayudará.
Sin embargo, usando declaraciones en el lugar correcto ayuda:
template<typename T> bool bar(T t)
{
return t > T();
}
namespace foo
{
class X {};
bool operator<(X, X);
using std::rel_ops::operator>;
}
int main()
{
X x;
bar(x); // now works: operator> found per ADL via the using declaration in `namespace foo`
}
Me resulta útil cuando se trabaja con bibliotecas con espacios de nombres profundamente anidados. La biblioteca Boost es un ejemplo de ello. boost::numeric::ublas::matrix<double> m
escritura de imágenes boost::numeric::ublas::matrix<double> m
todo el lugar ...
Lo que se debe evitar es using namespace
de using namespace
en un archivo de encabezado, ya que esto tiene el potencial de atornillar de forma real cualquier programa que incluya dicho encabezado. Siempre coloque using namespace
declaraciones de using namespace
en archivos .cpp / .cxx, de modo que esté restringido al alcance del archivo.
Por un lado, esta es la manera de usar las sobrecargas de operadores en un espacio de nombres (por ejemplo, using namespace std::rel_ops;
o using namespace boost::assign;
)
La brevedad es también un argumento fuerte. ¿Realmente disfrutarías escribiendo y leyendo std::placeholders::_1
lugar de _1
? Además, cuando escribe código en estilo funcional, estará usando una gran cantidad de objetos en el std
nombres std
y de boost
.
Otro uso importante (aunque normalmente uno no importa espacios de nombres completos) es habilitar la búsqueda dependiente de argumentos:
template <class T>
void smart_swap(T& a, T& b)
{
using std::swap;
swap(a, b);
}
Si el intercambio está sobrecargado por algún tipo de T en el mismo espacio de nombres que T, esto usará esa sobrecarga. Si en su lugar llamara explícitamente a std::swap
, no se consideraría esa sobrecarga. Para otros tipos esto recae en std::swap
.
Por cierto, una declaración / directiva de uso no anula el propósito de los espacios de nombres, ya que siempre puede calificar completamente el nombre en caso de ambigüedad.