Curso de C++ v2.0
Consultas, lista de correo 'C++ Con Clase' 'C++ Con Clase' página de entrada Librerías estándar C Tabla de contenido Contactar con Webmaster
*Introducción
*1 Toma de contacto
*2 Variables I
*3 Funciones I: Declaración y definición
*4 Operadores I
*5 Sentencias
*6 Declaración de variables
*7 Normas para la notación
*8 Cadenas de caracteres
*9 Conversión de tipos
*10 Variables II: Arrays
*11 Variables III: Estructuras
*12 Variables IV: Punteros 1
*13 Operadores II: Más operadores
*14 Operadores III: Precedencia
*15 Funciones II: Parámetros por valor y referencia
*16 Variables V: Uniones
*17 Variables VI: Punteros 2
*18 Operadores IV: De bits y condicional
*19 Definición de tipos
*20 Funciones III
*21 Funciones IV: Sobrecarga
*22 Operadores V: Sobrecarga
*23 El preprocesador
*24 Funciones V: Recursividad
*25 Variables VII: Modificadores
*26 Espacios con nombre
 . Declaraciones y definiciones
 . Utilidad
 . Espacios anónimos
 . Espacio global
 . Espacios anidados
*27 Clases I: Definiciones
*28 Declaración de clases
*29 Constructores
*30 Destructores
*31 El puntero this
*32 Sistema de protección
*33 Modificadores para miembros
*34 Más sobre funciones
*35 Operadores sobrecargados
*36 Herencia
*37 Funciones virtuales
*38 Derivación múltiple
*39 Trabajar con ficheros
*40 Plantillas
*41 Punteros a miembros
*42 Castings
*43 Excepciones
*Ejemplos capítulos 1 a 6
*Ejemplos capítulos 8 y 9
*A Palabras reservadas C/C++
*B Trigrafos y símbolos alternativos
*C Librerías estándar
*D Streams
<< < > >>

26 Espacios con nombre

Ya los hemos usado en los ejemplos, pero aún no hemos explicado por qué lo hacemos ni qué significan ni para qué sirven.

En cuanto a la utilidad los espacios con nombre nos ayudan a evitar problemas con identificadores en grandes proyectos. Nos permite, por ejemplo, que existan variables o funciones con el mismo nombre, declaradas en diferentes ficheros fuente, siempre y cuando se declaren en distintos espacios con nombre.

Declaraciones y definiciones  

Sintaxis para crear un espacio con nombre:

namespace [<identificador>] {
...
<declaraciones y definiciones>
...
}

Veamos un ejemplo:

// Fichero de cabecera "puntos.h"
namespace 2D {
   struct Punto {
      int x;
      int y;
   };
}

namespace 3D {
   struct Punto {
      int x;
      int y;
      int z;
   };
}// Fin de fichero

Este ejemplo crea dos versiones diferentes de la estructura Punto, una para puntos en dos dimensiones, y otro para puntos en tres dimensiones.

Sintaxis para activar un espacio para usar por defecto, esta forma se conoce como forma directiva de "using":

using namespace <identificador>;

Ejemplo:

#include "puntos.h"
using namespace 2D; // Activar el espacio con nombre 2D

Punto p1; // Define la variable p1 de tipo 2D::Punto
3D::Punto p2; // Define la variable p2 de tipo 3D::Punto
...

Sintaxis para activar un identificador concreto dentro de un espacio con nombre, esta es la forma declarativa de "using":

using <nombre_de_espacio>::<identificador>;

Ejemplo:

#include "puntos.h"

using 3D::Punto; // Usar la declaración de Punto 
                 // del espacio con nombre 3D
...

Punto p2; // Define la variable p2 de tipo 3D::Punto
2D::Punto p1; // Define la variable p1 de tipo 2D::Punto
...

Sintaxis para crear un alias de un espacio con nombre:

namespace <alias_de_espacio> = <nombre_de_espacio>;

Ejemplo:

namespace nombredemasiadolargoycomplicado {
...
declaraciones
...
}
...
namespace ndlyc = nombredemasiadolargoycomplicado; // Alias
...

Utilidad  

Este mecanismo permite reutilizar el código en forma de librerías, que de otro modo no podría usarse. Es frecuente que diferentes diseñadores de librerías usen los mismos nombres para cosas diferentes, de modo que resulta imposible integrar esas librerías en la misma aplicación. Por ejemplo un diseñador crea una librería matemática con una clase llamada "Conjunto" y otro una librería gráfica que también contenga una clase con ese nombre. Si nuestra aplicación incluye las dos librerías, obtendremos un error al intentar declarar dos clases con el mismo nombre.

El nombre del espacio funciona como un prefijo para las variables, funciones o clases declaradas en su interior, de modo que para acceder a una de esas variables se tiene que usar un especificador de ámbito (::), o activar el espacio con nombre adecuado.

Por ejemplo:

#include <iostream>

namespace uno {
int x;
}

namespace dos {
int x;
}

using namespace uno;

int main() {
   x = 10;
   dos::x = 30;
   
   std::cout << x << ", " << dos::x << std::endl;
   std::cin.get();
   return 0;
}

En este ejemplo hemos usado tres espacios con nombre diferentes: "uno", "dos" y "std". El espacio "std" se usa en todas las librerías estándar, de modo que todas las funciones y clases estándar se declaran y definen en ese espacio.

Hemos activado el espacio "uno", de modo que para acceder a clases estándar como "cout", tenemos que especificar el nombre: "std::cout".

También es posible crear un espacio con nombre a lo largo de varios ficheros diferentes, de hecho eso es lo que se hace con el espacio "std", que se define en todos los ficheros estándar.

Espacios anónimos  

¿Espacios con nombre sin nombre?

Si nos fijamos en la sintaxis de la definición de un espacio con nombre, vemos que el nombre es opcional, es decir, podemos crear espacios con nombre anónimos.

Pero, ¿para qué crear un espacio anónimo?. Su uso es útil para crear identificadores accesibles sólo en determinadas zonas del código. Por ejemplo, si creamos una variable en uno de estos espacios en un fichero fuente concreto, la variable sólo será accesible desde ese punto hasta el final del fichero.

namespace Nombre {
   int f();
   char s;
   void g(int);
}
namesmace {
   int x = 10;
}
// x sólo se puede desde este punto hasta el final del fichero
// Resulta inaccesible desde cualquier otro punto o fichero

namespace Nombre {
   int f() {
      return x; 
   }
}

Espacio global  

Cualquier declaración hecha fuera de un espacio con nombre pertenece al espacio global.

Precisamente porque las librerías estándar declaran todas sus variables, funciones, clases y objetos en el espacio "std", es necesario usar las nuevas versiones de los ficheros de cabecera estándar: "iostream", "fstream", etc. Y en lo que respecta a las procedentes de C, hay que usar las nuevas versiones que comienzan por 'c' y no tienen extensión: "cstdio", "cstdlib", "cstring", etc...". Todas esas librerías han sido rescritas en el espacio con nombre "std". Si usamos los ficheros de cabecera de C estaremos declarando las variables, estructuras y funciones en el espacio global.

Espacios anidados  

Los espacios con nombre se pueden anidar:

#include <iostream>

namespace uno {
   int x;
   namespace dos {
      int x;
      namespace tres {
         int x;
      }
   }
}

using std::cout;
using std::endl;
using uno::x;

int main() {
   x = 10; // Declara x como uno::x
   uno::dos::x = 30;
   uno::dos::tres::x = 50;
   
   cout << x << ", " << uno::dos::x << 
      ", " << uno::dos::tres::x << endl;
   std::cin.get();
   return 0;
}
<< < > >>
Free Web Hosting