Anuncios

Bienvenidos sean a este post, hoy hablaremos sobre un tema muy particular.

Anuncios

Un inconveniente que podemos tener en nuestros codigos, especialmente en los mas largos, es la repeticion de nombres para nuestras variables, funciones y otros elementos. Lo cual puede llevar a generar inconvenientes al momento de compilarlo. Estos son muy parecidos a las clases tanto en la definicion como en la estructura pero antes hablemos de algunas caracteristicas:

  • Los elementos declarados dentro del espacio de nombres son propiedad del mismo.
  • Todos los elementos son de visibilidad publica
  • Los espacios de nombres se pueden anidar dentro de otros espacios de nombres
  • Se puede definir funciones dentro o fuera del cuerpo del mismo
  • Si se define fuera debe ser identificada por el nombre del espacio de nombres
Anuncios

Antes de comenzar a hablar sobre ellos veamos como es su sintaxis:

namespace nombre {
  ... instrucciones ...
}
Anuncios

Siempre ira primero la palabra namespace seguido del nombre que lo identificara. Dentro del bloque pondremos todos los elementos que contendra, como dijimos anteriormente pueden ser variables, funciones, clases y otros, y siempre que queramos acceder debemos anteponer el nombre del namespace. Esto debe hacerse de la siguiente manera:

nombre::elemento
Anuncios

Siempre usaremos primero el nombre del namespace y luego el elemento. Estos a su vez seran unidos porr el operador de resolucion de nombre pero si observan bien este lo hemos estado usando en nuestros codigos, les dejo un ejemplo:

#include <iostream>

int main()
{
        std::cout << "Hola, Mundo!" << std::endl;
        return 0;
}
Anuncios

Este es el clasico ejemplo para mostrar el mensaje de Hola, Mundo. En este, y al igual que hemos visto en otros ejemplos, siempre hemos utilizado un namespace. En este caso, es std donde se encuentran las distintas funciones que usamos. Para poder acceder usamos lo comentado anteriormente, primero pasamos el namespace, seguido del operador de resolucion y finalmente la funcion a ejecutar. Pero nosostros podemos designar el namespace que deseamos usar, tomemos el codigo anterior y hagamos la siguiente modificacion:

#include <iostream>

using namespace std;

int main()
{
        cout << "Hola, Mundo!" << endl;
        return 0;
}
Anuncios

La primera modificacion fue agregar a using namespace. Este servira para indicarle al codigo que debe usarse ese namespace para todas las funciones. Por lo tanto, ya no necesitamos especificarlo y por ende lo removimos de las funciones. Si lo compilan y prueban veran que sigue funcionando de la misma manera. Pasemos a crear nuestro propio namespace, para ello tomemos el codigo anterior y realicemos la siguiente modificacion:

#include <iostream>

using namespace std;

namespace Primero {
        int numero;
        void incrementar() {
                cout << "Incrementado: " << numero++ << endl;
        }
}

namespace Segundo {
        int numero;
        void incrementar() {
                cout << "Incremented: " << numero++ << endl;
        }
}

int main()
{
        incrementar();
        return 0;
}
Anuncios

En este caso, creamos dos namespace con distintos nombres pero con el mismo contenido. En ambos tenemos una variable con el mismo nombre y una funcion con el mismo nombre donde realizamos la misma tarea. En ambas funciones incrementamos la variable anterior y la mostramos pero la unica diferencia es el mensaje que mostraremos junto al incremento. En el main, llamamos a la funcion pero no especificaremos ningun namespace. Compilemos y veamos que sucede:

$ g++ nombre.cpp -o nombre
nombre.cpp: In function ‘int main()’:
nombre.cpp:21:9: error: ‘incrementar’ was not declared in this scope
   21 |         incrementar();
      |         ^~~~~~~~~~~
nombre.cpp:21:9: note: suggested alternatives:
nombre.cpp:7:14: note:   ‘Primero::incrementar’
    7 |         void incrementar() {
      |              ^~~~~~~~~~~
nombre.cpp:14:14: note:   ‘Segundo::incrementar’
   14 |         void incrementar() {
      |              ^~~~~~~~~~~
$
Anuncios

Primero nos dijo que la funcion no esta declarada dentro de nuestro rango y luego nos sugiere las que podemos utilizar. Entonces, volvamos al codigo anterior y modifiquemos el main de la siguiente manera:

int main()
{
        Primero::incrementar();
        Segundo::incrementar();
        return 0;
}
Anuncios

Ahora vamos a llamar a ambas funciones y para ello especificamos los namespace de cada uno. Si lo compilamos y ejecutamos debemos tener la siguiente salida:

$ ./nombre
Incrementado: 1
Incremented: 1
$
Anuncios

Se llamo correctamente a cada una. Vamos con los primeros detalles, todo lo que dentro del namespace solo es afectado por los que esten dentro del mismo, salvo que le pasemos el namespace desde donde lo hagamos, y podemos repetirlo todas las veces necesarias siempre y cuando se encuentren en su namespace. Volvamos al codigo anterior y modifiquemos el namespace Segundo de la siguiente manera:

namespace Segundo {
        int numero;
        void incrementar() {
                cout << "Incremented: " << ++Primero::numero << endl;
        }
}
Anuncios

En la funcion le decimos que la variable a incrementar es la que se encuentra en el namespace Primero, en lugar de la propia. El resto sigue siendo el mismo namespace. Compilemos y veamos como es la salida:

$ ./nombre
Incrementado: 1
Incremented: 2
$
Anuncios

Como pueden ver ahora trabajamos con la variable del namespace Primero. Esto implica de que sin importar el lugar desde donde lo llamemos siempre que especifiquemos el namespace, el compilador sabra donde ubicarlo. Tomemos el codigo nuevamente y hagamos la siguiente modificacion:

#include <iostream>

using namespace std;

namespace Primero {
        class Clase
        {
        public:
                int numero=10;
                void incrementar() {
                  cout << "Incrementado: " << ++numero << endl;
                }
        };
}

namespace Segundo {
        int numero;
        void incrementar() {
                cout << "Incremented: " << ++numero << endl;
        }
}

int main()
{
        Primero::Clase objeto;
        objeto.incrementar();
        Segundo::incrementar();
        return 0;
}
Anuncios
Anuncios

La primera modificacion es en el namespace Primero donde agregamos una clase. Esta contendra en la parte publica la variable y la funcion anterior. Siguen haciendo lo mismo y a la variable la iniciamos con un valor. En el otro namespace volvemos a hacer que incremente la variable del namespace. Y la ultima modificacion la hicimos en el main, donde crearemos un objeto de la clase en el namespace Primero. Tal como en los otros casos debemos pasar primero el namespace y luego la clase, y desde este objeto llamaremos al metodo incrementar. Lo siguiente sera llamar al metodo incrementar de Segundo. Compilemos y veamos como es su salida:

$ ./nombre
Incrementado: 11
Incremented: 1
$
Anuncios

Para ir finalizando podemos tener namespace anidados. Es decir, namespace internos. Tomemos nuestro codigo y realicemos la siguiente modificacion:

#include <iostream>

using namespace std;

namespace Primero {
  namespace Interno {
    namespace Dentro {
        class Clase
        {
        public:
                int numero=10;
                void incrementar() {
                  cout << "Incrementado: " << ++numero << endl;
                }
        };
    }
  }
}

namespace Segundo {
        int numero;
        void incrementar() {
                cout << "Incremented: " << ++numero << endl;
        }
}

int main()
{
        Primero::Interno::Dentro::Clase objeto;
        objeto.incrementar();
        Segundo::incrementar();
        return 0;
}
Anuncios
Anuncios

Hicimos pocas modificaciones con repecto al codigo anterior. El namespace modificado fue Primero donde agregamos dos nuevos namespace llamados Interno y Dentro. Cada cual dentro del otro y en el ultimo tenemos la clase. Esto hara que para llegar debamos declarar todo el path o los namespace. Por esto, en el main para crear el objeto debemos pasar todos los namespace que contienen a nuestra clase. Si lo comparan con el codigo anterior son las unicas diferencias. Si lo compilan y ejecutan deben obtener el mismo resultado. Como dijimos esto nos permite establecer de mejor manera los elementos en nuestro codigo y evitar inconvenientes al momento de repetirlos. Ya sea al proposito o sin darnos cuenta, porque si bien en estos codigos no tienen ningun sentido. En codigos mas largos y amplios con distintas librerias los namespace puede pasar a ser fundamentales para eviar errores. Y cabe aclarar que estos no impiden que se produzcan pero si lo minimiza en todo lo posible.

Anuncios

En resumen, hoy hemos visto namespace, que es, para que sirve, como se implementa,, las distintas variantes que podemos tener, asi como tambien una serie de ejemplos para ver como se implementan. Espero les haya resultado de utilidad sigueme en tumblr, Twitter o Facebook para recibir una notificacion cada vez que subo un nuevo post en este blog, nos vemos en el proximo post.

Anuncios

Donación

Es para mantenimento del sitio, gracias!

$1.50