MQL5超入門(5)/関数のオーバーロードとは

某所で、MT4の初心者さん相手にサポートをしていると、ときどき面白いことをしてくれる人に出会えます。
その人は、カスタムインジケータをドロップしたのに何も表示されなくて困っているとのことで、私は症状を伺いつつ、どういう使い方や環境のもとで表示されなくなるのか推理してゆくのですが、その人の事例では、さっぱり原因が分かりませんでした。


例えば、コンパイルできないレベルの超・初心者なら、インジケータのサブウィンドウも表示できないはず…なのに、サブウィンドウは表示されている。
ラインの色を黒にしていたら、背景の黒と混ざって見えないとか?…そこで、ラインの色を変えないでドロップさせても改善しない。
0〜-100 の範囲で表示するインジケータを 0〜100で表示させようとするから見えない…という訳でもない。
start() が呼ばれないと描画されないインジで、start() が呼ばれない環境に陥っている?
そもそも、計算に必要なヒストリカルデータが無い?
…だとしたら、標準機能のインジケータも表示できないはず…ところが、標準のMACDは問題ない。


という感じで、これは私の手には負えないかもと、半分あきらめモードだったのですが、翌日、その人の操作手順を聞いてみると、
なぜか、MetaEditor のEA作成Wizard を触っているようでした。
フリーのインジケータをダウンロードしてから、EA作成Wizard を起動して中身が空っぽのインジケータを作ってチャートにドロップしていたら、それは表示されないですよ・・・(泣
mq4 ファイルをダブルクリックで開いて立ち上がるMetaEditor の左上の新規作成ボタンは、なんとなく追加ボタンに見えますもんね・・・押したくなりますよね・・・(涙


とまぁ、原因が分かれば話は簡単で、ここを紹介して無事解決したのですが、初心者相手のサポートの難しさを痛感した1日でした。




さて、本題のMQL5超入門(5)です。
これまで4回に渡ってMQL5のデータ型について説明しましたが、これからは関数絡みのMQL4との微妙な違いについてとりあげます。
知らなくても移植には困らない内容ばかりになりますが、将来、サンプルコードを読み解く際に困惑しなくてすむかなと思ってます。

関数のオーバーロードとは

MQL5 では、引数だけが異なる関数を同じ名前で宣言できます。これを関数のオーバーロードができると言います。
具体的には、

void MyAlert(string s)  //1つ目 文字型を受ける
{
  Alert("Message is ",s);
}
void MyAlert(datetime tm) //2つ目 時刻型を受ける
{
  Alert("Time is ",TimeToStr(tm,TIME_MINUTES));
}

のように、2つの MyAlert() という関数を用意しておくと、

MyAlert("error");       // 引数が文字なので、1つ目のMyAlert がよばれる
MyAlert(TimeCurrent()); // 引数が時刻なので、2つ目のMyAlert がよばれる

ということが出来ます。引数の個数が違うだけでも同じ名前で関数を作れます。
メリットには、処理目的が同じ関数を1つの関数名にまとめておける ( = 人間が覚えるべき関数名が減る) という利点があります。




次に、MQL5 の標準関数でのオーバーロードの実例を紹介します。
サーバの終値データを、自作の配列にコピーする関数として CopyClose があり、
その引数は3タイプ定義されています。

int  CopyClose(
   string           symbol_name,       // シンボル名
   ENUM_TIMEFRAMES  timeframe,         // タイムフレーム
   int              start_pos,         // コピー開始位置
   int              count,             // コピーする個数
   double           close_array      // コピー先配列名
   );

int  CopyClose(
   string           symbol_name,       // シンボル名
   ENUM_TIMEFRAMES  timeframe,         // タイムフレーム
   datetime         start_time,        // コピー開始時刻
   int              count,             // コピーする個数
   double           close_array      // コピー先配列名
   );

int  CopyClose(
   string           symbol_name,       // シンボル名
   ENUM_TIMEFRAMES  timeframe,         // タイムフレーム
   datetime         start_time,        // コピー開始時刻
   datetime         stop_time,         // コピー終了時刻
   double           close_array[]      // コピー先配列名
   );

サーバの終値データを従来どおりの配列とみなして範囲コピーするなら1番目の関数、
8/1 から 20 本分のデータをコピーしたいなら、2番目の関数、
8/1 から 8/30 までのデータが欲しい時は、3番目の関数....と使い分けることができます。
(ちなみに、実際に何本コピー出来たか?がこの関数の返り値になっています。)


このような Copy**** で始まる関数は10種類あって、

CopyBuffer // 定義済みのindicatorバッファ配列をコピーする。
CopyClose
CopyHigh
CopyLow
CopyOpen
CopyRates // Rates構造体配列をコピーする。
CopyRealVolume //出来高
CopySpread //スプレッド
CopyTickVolume //Tick更新回数
CopyTime

これらは全て3タイプの関数をオーバーロードしているので、実質30個の関数が含まれています。
オーバーロードの仕組みが無いと、プログラミング時に 30 個も関数名を書き分けないといけないのが、10 個で済むところに、ささやかなありがたみを感じてくださいませ..。


移植を前提としている人は、オーバーロードした関数を自作する必要はありませんが、MQL5 の標準関数はオーバーロードされていることが多いので、引数に注意して使いこなしましょう..。