命名空间

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

namespace name of_space {

  //函数、类和变量定义的列表

}

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

namespace ProjectData

{

class DataManager

  {

public:

   void              LoadData() {}

  };

void Func(DataManager& manager) {}

}

//+------------------------------------------------------------------+

//| 脚本程序起始函数                                                  |

//+------------------------------------------------------------------+

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函数导入的所有函数都包含在相同名称的命名空间中。这使得编译器能够清楚地确定要调用的函数。

另见

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