Espaços de nomes

O namespace (espaço para nome) é uma área especialmente declarada dentro da qual são definidos vários identificadores: variáveis, funções, classes, etc. A. È definido com ajuda da palavra-chave namespace:

namespace nome_espaço { 
  // lista de definições de funções, de classes e de variáveis
}

O uso do namespace permite dividir o namespace global em subespaços. Todos os identificadores no namespace estão disponíveis um para o outro sem especificação. Para acessar membros do namespace de fora, é usado o operador :: (operação de resolução de contexto).

namespace ProjectData
{
class DataManager
  {
public:
   void              LoadData() {}
  };
void Func(DataManagermanager) {}
}
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
//--- trabalhando com o namespace ProjectData
   ProjectData::DataManager mgr;
   mgr.LoadData();
   ProjectData::Func(mgr);
  }

Os namespace são usados para organizar o código como grupos lógicos e para evitar conflitos de nomes que podem ocorrer quando são usadas várias bibliotecas em um programa. Nesses casos, cada biblioteca pode ser declarada em seu namespace, para que possa acessar explicitamente as funções e classes necessárias de cada biblioteca.

Um namespace pode ser declarado em vários blocos em um ou em vários arquivos. O compilador reúne todas as partes durante o pré-processamento e namespace resultante contém todos os membros declarados em todas as partes. Suponhamos que implementemos a classe A no arquivo incluído Sample.mqh:

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

Queremos usar essa classe em nosso projeto, mas já temos a classe A. Para poder usar as duas classes e evitar conflitos de identidade, basta agrupar o arquivo incluído em um namespace:

//--- declaramos a primeira classe A
class A
  {
public:
                     A() {Print(__FUNCTION__);}
  };
//--- embrulhamos a classe A do arquivo "Sample.mqh" no namespace "Library" para evitar conflitos
namespace Library
{
#include "Sample.mqh"
}
//--- adicionamos outra classe ao namespace "Library"
namespace Library
{
class B
  {
public:
                     B() {Print(__FUNCTION__);}
  };
}
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
//--- usamos a classe A do namespace global
   A a1;
//--- usamos as classes A e B do namespace "Library"
   Library::A a2;
   Library::B b;
  }
//+------------------------------------------------------------------+
 
/*
Resultado:
   A::A
   Library::A::A
   Library::B::B
*/

Os namespace podem ser aninhados. Um namespace aninhado tem acesso ilimitado aos membros do seu espaço pai, mas os membros do espaço pai não têm acesso ilimitado ao espaço para nome aninhado.

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;}
}

 

Namespace global

Se o identificador não for declarado explicitamente no namespace, ele é implicitamente considerado parte do namespace global. Para especificar explicitamente um identificador global, use operador de escopo de resolução sem nome. Isso permite distinguir esse identificador de qualquer outro elemento com o mesmo nome localizado em um namespace diferente. Por exemplo, ao importar uma função:

#import "lib.dll"
int Func();
#import
//+------------------------------------------------------------------+
//|  Alguma das nossas funções                                              |
//+------------------------------------------------------------------+
int Func()
  {
   return(0);
  }
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
//+--- chamada de função impotada
   Print(lib::Func());
//+--- chamada de nossa função
   Print(::Func());
  }

Nesse caso, todas as funções importadas da DLL são incluídas no namespace com o mesmo nome. Isso permite que o compilador determine exclusivamente qual função chamar.

Véase también

Variáveis Globais, Variáveis Locais, Visibilidade Escopo e Tempo de Vida de Variáveis, Criação e Exclusão de Objetos