Espacios de nombres

Un espacio de nombres es una zona especialmente declarada, dentro de la cual se determinan distintos identificadores: variables funciones, clases, etcétera. Se establece con la ayuda de la palabra clave namespace:

namespace nombre_espacios { 
  // lista de definiciones de funciones, clases y variables
}

El uso de namespace permite dividir el espacio global de nombres en varios espacios. Todos los identificadores dentro del espacio de nombres están disponibles unos para otros sin . Para acceder a los miembros del espacio de nombres, se usa el operador :: (operación de resolución de ámbito).

namespace ProjectData
{
class DataManager
  {
public:
   void              LoadData() {}
  };
void Func(DataManagermanager) {}
}
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
//--- trabajando con el espacio de nombres ProjectData
   ProjectData::DataManager mgr;
   mgr.LoadData();
   ProjectData::Func(mgr);
  }

Los espacios de nombres se usan para organizar el código en forma de grupos lógicos y para evitar conflictos de nombres que pueden aparecer cuando se usan varias bibliotecas en el programa. En tales casos, podemos declarar cada biblioteca en su propio espacio de nombres, para después recurrir explícitamente a las funciones y clases necesarias de cada biblioteca.

El espacio de nombres puede declararse en varios bloques en un archivo o en varios de ellos. El compilador combina todas las partes durante el procesamiento preliminar, así que el espacio de nombres obtenido como resultado contendrá todos los miembros declarados en todas las partes. Supongamos que hemos implementado la clase A en el archivo de inclusión Sample.mqh:

//+------------------------------------------------------------------+
//|                                                       Sample.mqh |
//+------------------------------------------------------------------+
class A
  {
public:
                     A() {Print(__FUNCTION__);}
  };

Queremos usar esta clase en nuestro proyecto, pero ya disponemos de una clase A. Para tener la posibilidad de usar ambas clases y evitar un conflicto de identificadores, bastará con envolver el archivo de inclusión en un espacio de nombres:

//--- declaramos la primera clase A
class A
  {
public:
                     A() {Print(__FUNCTION__);}
  };
//--- envolvemos la clae A del archivo "Sample.mqh" en el espacio de nombres "Library" para evitar conflictos
namespace Library
{
#include "Sample.mqh"
}
//--- añadimos otra clase más en el espacio de nombres "Library"
namespace Library
{
class B
  {
public:
                     B() {Print(__FUNCTION__);}
  };
}
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
//--- usamos la clase A del espacio de nombres global
   A a1;
//--- usamos las clases A y B del espacio de nombres "Library"
   Library::A a2;
   Library::B b;
  }
//+------------------------------------------------------------------+
 
/*
Resultado:
   A::A
   Library::A::A
   Library::B::B
*/

Los espacios de nombres pueden ser anidados. Un espacio de nombres anidado tiene acceso ilimitado a los miembros de su espacio padre, pero los miembros del espacio padre no tienen acceso ilimitado al espacio de nombres anidado.

namespace General
{
int Func();
 
namespace Details
{
 int Counter;
 int Refresh()  {return Func(); }
}
 
int GetBars()   {return(iBars(Symbol(), Period()));};
int Size(int i) {return Details::Counter;}
}

 

Espacio global de nombres

Si el identificador no ha sido explícitamente declarado en el espacio de nombres, se considerará que entra de forma implícita en el espacio global de nombres. Para indicar explícitamente un identificador global, use un operador de resolución de ámbito sin nombre. Esto permitirá distinguir este identificador de cualquier otro elemento con el mismo nombre que se encuentre en otro espacio de nombres.  Por ejemplo, al importar una función:

#import "lib.dll"
int Func();
#import
//+------------------------------------------------------------------+
//|  Alguna función                                              |
//+------------------------------------------------------------------+
int Func()
  {
   return(0);
  }
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
//+--- llamando la función importada
   Print(lib::Func());
//+--- llamando nuestra función
   Print(::Func());
  }

En este caso, todas las funciones importadas desde la DLL han sido incluidas en el espacio de nombres homónimo. Esto ha permitido al compilador determinar de forma unívoca qué función debemos llamar.

Véase también

Variables globales, Variables locales, Visibilidad y tiempo de vida de variables, Creación y eliminación de objetos