名前空間
名前空間は、変数、関数、クラスなど、さまざまなIDが定義されている特別に宣言された領域で、namespaceキーワードを使用して設定されます。
namespace name of_space {
// 関数、クラス、変数定義のリスト
}
|
「namespace」を適用すると、グローバル名前空間をサブスペースに分割できます。名前空間内のすべてのIDは、仕様なしで相互に利用可能です。::演算子(コンテキスト解決操作)は、外部から名前空間メンバーにアクセスするために使用されます。
namespace ProjectData
{
class DataManager
{
public:
void LoadData() {}
};
void Func(DataManager& manager) {}
}
//+------------------------------------------------------------------+
//| スクリプトプログラム開始関数 |
//+------------------------------------------------------------------+
void OnStart()
{
//--- ProjectData名前空間の操作
ProjectData::DataManager mgr;
mgr.LoadData();
ProjectData::Func(mgr);
}
|
名前空間は、プログラムで複数のライブラリが使用されるときに発生する可能性のある名前の競合を回避するために、論理グループの形式でコードを配置するために使用されます。そのような場合、各ライブラリをその名前空間で宣言して、各ライブラリの必要な関数とクラスに明示的にアクセスできるようになります。
名前空間は、1つまたは複数のファイルの複数のブロックで宣言できます。コンパイラは、前処理中にすべての部分を結合し、結果の名前空間には、すべての部分で宣言されたすべてのメンバが含まれます。Sample.mqhインクルードファイルに実装されたAクラスがあると仮定します。
//+------------------------------------------------------------------+
//| Sample.mqh |
//+------------------------------------------------------------------+
class A
{
public:
A() {Print(__FUNCTION__);}
};
|
このクラスをプロジェクトで使用したいのですが、Aクラスはすでに存在します。両方のクラスを使用してIDの競合を回避するには、含まれているファイルを名前空間でラップするだけです。
//--- 1番目のAクラスを宣言
class A
{
public:
A() {Print(__FUNCTION__);}
};
//--- 競合を避けるために、Library名前空間のSample.mqhファイルにAクラスをラップする
namespace Library
{
#include "Sample.mqh"
}
//--- Library名前空間にクラスを追加する
namespace Library
{
class B
{
public:
B() {Print(__FUNCTION__);}
};
}
//+------------------------------------------------------------------+
//| スクリプトプログラム開始関数 |
//+------------------------------------------------------------------+
void OnStart()
{
//--- グローバル名前空間のAクラスを使用
A a1;
//--- Library名前空間のAクラスを使用<分節
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;}
}
|
グローバル名前空間
名前空間で明示的に宣言されていないIDは、グローバル名前空間の暗黙的な部分と見なされます。グローバルIDを明示的に設定するには、名前なしでスコープ解決演算子を使用します。これにより、このIDを、異なる名前空間にある同じ名前の他の要素と区別できます。例として、下記の関数をインポートするとします。
#import "lib.dll"
int Func();
#import
//+------------------------------------------------------------------+
//| 関数 |
//+------------------------------------------------------------------+
int Func()
{
return(0);
}
//+------------------------------------------------------------------+
//| スクリプトプログラム開始関数 |
//+------------------------------------------------------------------+
void OnStart()
{
//+--- インポートされた関数を呼び出す
Print(lib::Func());
//+--- 関数を呼び出す
Print(::Func());
}
|
この場合、DLL関数からインポートされたすべての関数は、同じ名前の名前空間に含まれて、コンパイラは呼び出される関数を明確に決定できました。
参照
グローバル変数、ローカル変数、変数のアクセス権スコープとライフタイム、オブジェクトの作成と解徐