GeeksforGeeks
On enero 16, 2022 by adminLa declaración using namespace std se considera generalmente una mala práctica. La alternativa a esta declaración es especificar el espacio de nombres al que pertenece el identificador utilizando el operador de ámbito(::) cada vez que declaramos un tipo.
Aunque la declaración nos ahorra escribir std:: cada vez que deseamos acceder a una clase o tipo definido en el espacio de nombres std, importa la totalidad del espacio de nombres std al espacio de nombres actual del programa. Tomemos algunos ejemplos para entender por qué esto podría no ser tan bueno
Digamos que deseamos utilizar el cout del espacio de nombres std. Entonces escribimos
Ejemplo 1:
#include <iostream>
using
namespace
std;
cout <<
" Something to Display"
;
Ahora, en una fase posterior de desarrollo, deseamos utilizar otra versión de cout que está implementada de forma personalizada en alguna librería llamada «foo» (por ejemplo)
.
#include <foo.h>
#include <iostream>
using
namespace
std;
cout <<
" Something to display"
;
Nota que hay una ambigüedad, ¿a qué biblioteca apunta cout? El compilador puede detectar esto y no compilar el programa. En el peor de los casos, el programa puede seguir compilando pero llamar a la función equivocada, ya que nunca especificamos a qué espacio de nombres pertenecía el identificador.
Los espacios de nombres se introdujeron en C++ para resolver los conflictos de nombres de los identificadores. Esto aseguraba que dos objetos podían tener el mismo nombre y, sin embargo, ser tratados de forma diferente si pertenecían a diferentes espacios de nombres. Fíjate en que en este ejemplo ha ocurrido exactamente lo contrario. En lugar de resolver un conflicto de nombres, en realidad creamos un conflicto de nombres.
Cuando importamos un espacio de nombres estamos esencialmente tirando de todas las definiciones de tipos en el ámbito actual. El espacio de nombres std es enorme. Tiene cientos de identificadores predefinidos, por lo que es posible que un desarrollador pase por alto el hecho de que hay otra definición de su objeto previsto en la biblioteca std. Sin saberlo, puede proceder a especificar su propia implementación y esperar que se utilice en partes posteriores del programa. Así, existirían dos definiciones para el mismo tipo en el espacio de nombres actual. Esto no está permitido en C++, e incluso si el programa compila no hay forma de saber qué definición se está utilizando dónde.
La solución al problema es especificar explícitamente a qué espacio de nombres pertenece nuestro identificador utilizando el operador de ámbito (::). Así, una posible solución al ejemplo anterior puede ser
#include <foo>
#include <iostream>
std::cout <<
"Something to display"
;
foo::cout <
"Something to display"
;
Pero tener que escribir std:: cada vez que definimos un tipo es tedioso. También hace que nuestro código se vea más peludo con muchas definiciones de tipos y dificulta la lectura del código. Consideremos por ejemplo el código para obtener la hora actual en el programa
Ejemplo 2:
#include <chrono>
#include <iostream>
auto
start = std::chrono::high_performance_clock::now()
auto
stop
= std::chrono::high_peformance_clock::now();
auto
duration
= std::duration_cast<std::chrono::milliseconds>(stop - start);
El código fuente que está plagado de complicadas y largas definiciones de tipos no es muy fácil de leer. Esto es algo que los desarrolladores tratan de evitar ya que la mantenibilidad del código es principalmente importante para ellos.
Hay algunas maneras de resolver este dilema, es decir, especificar el espacio de nombres exacto sin ensuciar el código con palabras clave std.
Considere el uso de typedefs
Los typedefs nos salvan de escribir largas definiciones de tipos. En nuestro ejemplo 1, podríamos resolver el problema usando dos typedefs uno para la biblioteca std y otro para foo
#include <foo>
#include <iostream>
typedef
std::cout cout_std;
typedef
foo::cout cout_foo;
cout_std <<
"Something to write"
;
cout_foo <<
"Something to write"
;
En lugar de importar espacios de nombres enteros, importar un espacio de nombres truncado
En el ejemplo 2 podríamos haber importado sólo el espacio de nombres chrono bajo std.
#include <chrono>
#include <iostream>
using
std::chrono;
auto
start = high_performance_clock::now();
auto
stop = high_performance_clock::now();
auto
duration duration_cast<milliseconds>(stop - start);
También podemos utilizar la sentencia para importar un solo identificador. Para importar sólo std::cout podríamos utilizar
using std::cout;
Si aún así importa espacios de nombres enteros, intente hacerlo dentro de funciones o de ámbito limitado y no en el ámbito global.
Utilice la sentencia «using namespace std» dentro de definiciones de funciones o definiciones de clases o estructuras. Al hacerlo, las definiciones del espacio de nombres se importan a un ámbito local, y al menos sabemos dónde se pueden originar los posibles errores si surgen.
#include <isotream>
using
namespace
std;
void
foo()
{
using
namespace
std;
}
Conclusión.
Hemos discutido métodos alternativos para acceder a un identificador desde un espacio de nombres. En todos los casos, evite importar espacios de nombres enteros en el código fuente.
Aunque las buenas prácticas de codificación pueden tomar algún tiempo para aprender y desarrollar, generalmente pagan a largo plazo. Escribir un código limpio, sin ambigüedades y robusto y libre de errores debe ser la intención de cualquier desarrollador de programación.
Deja una respuesta