命名空间

namespace是一个特殊声明的区域,其中定义了各种ID:变量、函数、类等。其使用namespace关键字进行设置:

namespace name of_space { 
  //函数、类和变量定义的列表
}

应用'namespace'可以将全局的命名空间拆分为子空间。namespace中的所有ID都可以彼此使用,不需要特别指定。::操作符(语境解析操作)用于从外部访问命名空间(namespace)成员。

namespace ProjectData
{
class DataManager
  {
public:
   void              LoadData() {}
  };
void Func(DataManagermanager) {}
}
//+------------------------------------------------------------------+
//| 脚本程序起始函数                                                  |
//+------------------------------------------------------------------+
void OnStart()
  {
//--- 使用ProjectData命名空间
   ProjectData::DataManager mgr;
   mgr.LoadData();
   ProjectData::Func(mgr);
  }

命名空间(namespaces)用于以逻辑组的形式排列代码,并避免在程序中使用多个程序库时可能发生的名称冲突。在这种情况下,可以在其命名空间(namespaces)中声明每个程序库,以便显式访问每个程序库的必要函数和类。

命名空间(namespaces)可以在一个或多个文件中的多个块中声明。编译器在预处理期间将所有部分组合在一起,并且得到的命名空间包含所有部分中声明的所有成员。假设我们在Sample.mqh包含文件中实现了A类:

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

我们想在我们的项目中使用这个类,但是我们已经有A类。若要能够使用这两个类并要避免ID冲突,只需将包含文件包含在命名空间中:

//--- 声明第一个A类
class A
  {
public:
                     A() {Print(__FUNCTION__);}
  };
//--- 将Sample.mqh文件中的A类包含在“程序库”命名空间中,以避免出现冲突
namespace Library
{
#include "Sample.mqh"
}
//--- 在“程序库”命名空间中添加另一个类
namespace Library
{
class B
  {
public:
                     B() {Print(__FUNCTION__);}
  };
}
//+------------------------------------------------------------------+
//| 脚本程序起始函数                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
//--- 使用全局命名空间中的A类
   A a1;
//--- 使用“程序库”命名空间中的A和B类
   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;}
}

 

全局命名空间(Global namespace)

如果ID没有在命名空间中显式声明,则认为它是全局命名空间的隐式部分。要显式地设置全局ID,请使用范围解析操作符,无需命名。这将可以使您将这个ID与位于不同命名空间中具有相同名称的任何其他元素区分开来。例如,导入函数时:

#import "lib.dll"
int Func();
#import
//+------------------------------------------------------------------+
//|  某个函数                                              |
//+------------------------------------------------------------------+
int Func()
  {
   return(0);
  }
//+------------------------------------------------------------------+
//| 脚本程序起始函数                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
//+--- 调用导入函数
   Print(lib::Func());
//+--- 调用我们的函数
   Print(::Func());
  }

在本例中,从DLL函数导入的所有函数都包含在相同名称的命名空间中。这使得编译器能够清楚地确定要调用的函数。

另见

全局变量本地变量可视范围和变量的生命周期创建和删除对象