Пространства имен

Пространство имен — это специально объявленная область, в пределах которой определяются различные идентификаторы: переменные, функции, классы и и т. д. Задается с помощью ключевого слова namespase:

namespace имя_пространства { 
  // список определений функций, классов и переменных
}

Использование namespace позволяет разделить глобальное пространство имен на подпространства. Все идентификаторы в пределах пространства имен доступны друг другу без уточнения. Для доступа к членам пространства имен извне используется оператор :: (операция разрешения контекста).

namespace ProjectData
{
class DataManager
  {
public:
   void              LoadData() {}
  };
void Func(DataManagermanager) {}
}
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
//--- работа с пространством имен ProjectData 
   ProjectData::DataManager mgr;
   mgr.LoadData();
   ProjectData::Func(mgr);
  }

Пространства имен используются для организации кода в виде логических групп и с целью избежания конфликтов имен, которые могут возникнуть когда в программе используется несколько библиотек. В таких случаях каждую библиотеку можно объявить в своем пространстве имен, чтобы затем явно обращаться к нужным функциям и классам каждой библиотеки.

Пространство имен может быть объявлено в нескольких блоках в одном файле и в нескольких файлах. Компилятор соединит вместе все части во время предварительной обработки и полученное в результате пространство имен будет содержать все члены, объявленные во всех частях. Пусть у нас реализован класс A во включаемом файле Sample.mqh:

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

Этот класс мы хотим использовать в своем проекте, но у нас уже есть класс A. Чтобы иметь возможность использовать оба класса и избежать конфликта идентификаторов, достаточно включаемый файл обернуть в пространство имен:

//--- объявим первый класс A
class A
  {
public:
                     A() {Print(__FUNCTION__);}
  };
//--- обернем класс A из файла "Sample.mqh" в пространство имен "Library" для избежания конфликта
namespace Library
{
#include "Sample.mqh"
}
//--- добавим еще один класс в пространство имен "Library"
namespace Library
{
class B
  {
public:
                     B() {Print(__FUNCTION__);}
  };
}
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
//--- используем класс A из глобального пространства имен
   A a1;
//--- используем классы A и B из пространства имен "Library"
   Library::A a2;
   Library::B b;
  }
//+------------------------------------------------------------------+
 
/*
Результат:
   A::A
   Library::A::A
   Library::B::B
*/

Пространства имен могут быть вложенными. Вложенное пространство имен имеет неограниченный доступ к членам своего родительского пространства, но члены родительского пространства не имеют неограниченного доступа к вложенному пространству имен.

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

 

Глобальное пространство имен

Если идентификатор не объявлен явно в пространстве имен, он неявно считается входящим в глобальное пространство имен. Чтобы явно указать глобальный идентификатор, используйте оператор разрешения области видимости без имени. Это позволит отличать данный идентификатор от любого другого элемента с таким же именем, находящегося в другом пространстве имен.  Например, при импорте функции:

#import "lib.dll"
int Func();
#import
//+------------------------------------------------------------------+
//|  Некая наша функция                                              |
//+------------------------------------------------------------------+
int Func()
  {
   return(0);
  }
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
//+--- вызов импортированной функции
   Print(lib::Func());
//+--- вызов нашей функции
   Print(::Func());
  }

В данном случае все импортированные из DLL функции были включены в одноименное пространство имен. Это позволило компилятору однозначно определить какую функцию требуется вызвать.

Смотри также

Глобальные переменные, Локальные переменные, Область видимости и время жизни переменных, Создание и уничтожение объектов