mql5言語の特徴、微妙なニュアンスとテクニック - ページ 188

 
Nikolai Semko:
問題は、他のクラスのオブジェクト(ここではCTimer)がそのクラスのプロパティ(変数)であっても、あるクラスの 非静的メソッドを ポインタで起動することができるのか、ということです。

ないもちろん、別のオブジェクトへのポインタを渡して、そこでポインタを変更してメソッドを呼び出すこともできますが......メソッドの名前を知っている必要があるのです。

ZSは:しかし、昨日書いた、例@fxsaberを 使用して継承し、各クラスでOnTimerで呼び出されます 、唯一のタイマーがどのようなタイマー間隔を持ってチェックするループ内のベースクラスがあるだろうし、静的メソッドのメインタイマーの起動を実装します。

 
Nikolai Semko:
他のクラスのオブジェクト(この場合はCTimer)がそのクラスのプロパティ(変数)であっても、ポインタを使用してそのクラスの非静的メソッドを 実行することができるのか、という問題です。可能なのでしょうか?残念ながら、そうではありません。

- テンプレート

- インターフェース

 

のテンプレートがあります。

template <typename C> class Timer
{
public:
  Timer(C* c)
  : p(c)
  {}

  void OnTimer()
  {
    p->OnTimer();
  }
private:
  C* p;
}

class Handler
{
public:
  Handler()
  : t(this)
  {}

  void OnTimer() {}
private:
  Timer<Handler> t;
}

ここではタイマー自体の実装はなく、非静的関数を呼び出す例のみ(フォーラムに直接書いたので確認せず)

 

トレーディング、自動売買システム、トレーディング戦略のテストに関するフォーラム

MT5とスピードの関係

fxsaber, 2020.10.04 11:56

ブレーキがかかっている機械でプログラムが実行されているかどうかを判断します。

// Возвращает true, если тормозной VPS.
bool IsFreezeVPS()
{
  static bool FirstRun = true;
  static bool Res;
  
  if (FirstRun)
  {
    if (Res = ::GetMicrosecondCount() - ::GetMicrosecondCount())
      ::Alert("Warning: FreezeVPS - https://www.mql5.com/ru/forum/342090/page40#comment_18579094");
    
    FirstRun = false;
  }
  
  return(Res);
}
 
Nikolai Semko:
他のクラスのオブジェクト(この場合はCTimer)がこのクラスのプロパティ(変数)であっても、非静的クラスのメソッドを ポインタで実行するにはどうすればよいかという問題です。そして、それは可能なのでしょうか?残念ながら、そうではありません。

一般論としては、このような感じです。

#define  USING_STD

#include <STD\Time\Timer.mqh>

class CTest{
   _tTimerEvent<CTest> cEvent;
public:
   CTest(_tTimer* mTimer):cEvent(&this,mTimer){}
   void TimerEvent(_tTimerInfo &info){
      PrintFormat("Timer check in class at %llu, current delta %llu, count from last %u",info.lastTimer,info.delta,info.count);
   }
};

_tTimer gTimer1;
_tTimer gTimer2;

CTest gTest(&gTimer1);

int OnInit(void)
  {
   EventSetMillisecondTimer(20);
   ulong timer=GetMicrosecondCount();
   if (!gTimer1) gTimer1.Reset(timer,1000000); //1 s
   if (!gTimer2) gTimer2.Reset(timer,2000000).Function(TimerEvent); //2 s
   TimerControl(timer);
   return(INIT_SUCCEEDED);
  }

void OnDeinit(const int reason){
   TimerControl(GetMicrosecondCount());
// или gTimer.Free();
   EventKillTimer();
  }

void OnTick()
   {
   TimerControl(GetMicrosecondCount());
  }
  
void OnTimer(void)
  {
   TimerControl(GetMicrosecondCount());
  }
//+------------------------------------------------------------------+
void TimerControl(ulong fTimer){
   gTimer1.Control(fTimer);
   gTimer2.Control(fTimer);
}

void TimerEvent(_tTimerInfo &info){
   PrintFormat("Timer check in function %llu, current delta %llu, count from last %u",info.lastTimer,info.delta,info.count);
}

libはこちらからダウンロードできます。https://github.com/sva04091979/STD/tree/TimerEvent。 TimerEventブランチ、まだmasterにマージされていない。

 
Igor Makanu:

ないもちろん、別のオブジェクトへのポインタを渡して、そこでポインタを変更してメソッドを呼び出すこともできますが......メソッドの名前を知っている必要があるのです。

ZSは:しかし、昨日書いた、例@fxsaberを 使用して継承し、各クラスでOnTimerで呼び出されます 、唯一のタイマーがどのようなタイマー間隔、および静的メソッドのメインタイマーの起動を持ってチェックするループ内のベースクラスが実装されます。

Igor、fxsaberのコードについて理解できません。

Andrei Trukhanovich:

のテンプレートがあります。

タイマー自体の実装はなく、非静的な関数を呼び出す例のみ(フォーラムに直接書いたので確認してないです)

ありがとうございます。試してみました。何も出てきません。

ウラジミール・シマコフ

一般的にはこのような感じです。

ライブラリはこちらからダウンロードできます。https://github.com/sva04091979/STD/tree/TimerEvent。 TimerEventブランチ、まだmasterにマージしていません。

ありがとうございます。しかし、非静的なクラスメソッドをポインタで実行する方法も見つかっていません。


皆さんのおかげですが、私の知識が乏しいため、タスクの表現が適切でないか、皆さんの記事で解決策を見たことがないのかもしれません。
何が必要ですか?
以下はインジケーターの例です。
CTestTimerクラスのメソッドTimer4(青印)は、CTestTimerクラスのオブジェクトを生成したときのコンストラクタ実行の瞬間にCTimer クラスから(CTimer:: OnTimerメソッドのループ内で)CTimer::NewTimerクラスに渡されるポインタで起動します。
いろいろ試したのですが、CTestTimerクラスのメソッドTimer4(青 印)は、CTimer クラスのオブジェクトを生成したときのコンストラクタ実行の瞬間に、CTimer::NewTimerクラスのメソッドを起動することができます。デッドロックがある。このメソッドへのポインタを取得する方法はありません。C++では次のように動作します:typedef void (CTestTimer::*TFun)();
そして奇妙なエラーがあります:'Timer4' - pointer to this function type is not supported yet('Timer4' - pointer to this function type is not supported yet)
"For now" - まるでMQがこの質問をもっといい時まで取っておくかのようにです。

#property indicator_chart_window
#include <Timer.mqh> // https://www.mql5.com/ru/code/31306

//+------------------------------------------------------------------+
class CTestTimer {
 private:
   //typedef void (CTestTimer::*TFunc2)(); // так работает в C++, но здесь не работает
 public:
   int x4;
   CTestTimer() {
      x4=0;
      //TFunc2 p=CTestTimer::Timer4;
      //TFunc2 p=Timer4;
      //timers.NewTimer(700,p);
      timers.NewTimer(700,CTestTimer::Timer4); // ошибка 'Timer4' - pointer to this function type is not supported yet
   };
   ~CTestTimer(){};
   void Timer4() {
      x4++;
      if (x4==7) timers.KillTimer(CTestTimer::Timer4); // удаляем этот таймер
   }
};
//+------------------------------------------------------------------+


int x1=0;
int x2=0;
int x3=0;
CTestTimer X= new CTestTimer;
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int OnInit() {
   timers.NewTimer(500,  Timer1); // создаем новый таймер с периодом обновления 500   милисекунд и функцией-обраточником Timer1()
   timers.NewTimer(1000, Timer2); // создаем новый таймер с периодом обновления 1000  милисекунд и функцией-обраточником Timer2()
   timers.NewTimer(2000, Timer3); // создаем новый таймер с периодом обновления 2000  милисекунд и функцией-обраточником Timer3()
   timers.NewTimer(100,  Timer5); // создаем новый таймер с периодом обновления 100   милисекунд и функцией-обраточником Timer5()
   return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
void OnDeinit(const int reason) {
   Comment("");
}
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total, const int prev_calculated, const int begin, const double &price[]) {
   return(rates_total);
}
//+------------------------------------------------------------------+
void Timer1() {  // данная функция вызывается каждые 500 миллисекунд
   x1++;
   if (x1==50) timers.KillTimer(Timer1); // удаляем этот таймер
}
//+------------------------------------------------------------------+
void Timer2() {  // данная функция вызывается каждые 1000 миллисекунд
   x2++;
   if (x2==22) timers.KillTimer(Timer2); // удаляем этот таймер
}
//+------------------------------------------------------------------+
void Timer3() {  // данная функция вызывается каждые 2000 миллисекунд
   x3++;
   if (x3==10) timers.KillTimer(Timer3); // удаляем этот таймер
}
//+------------------------------------------------------------------+
void Timer5() {  // данная функция вызывается каждые 100 миллисекунд
   if (x1==50) timers.KillTimer(Timer5); // удаляем этот таймер
   Comment("x1=" +string(x1)+";\nx2="+string(x2)+";\nx3="+string(x3)+";\nx3="+string(X.x4)+"\nВсего таймеров - "+string(timers.GetN()));
}
//+------------------------------------------------------------------+
MQL5言語の現状では、この問題に対する解決策はないようです
 
Nikolai Semko:

Igor、どの fxsaber コードについて話しているのか理解できない。

https://www.mql5.com/ru/forum/325418/page4#comment_16116740

このコードの値は...。そうですね、ダイナミック・オブジェクトは、コードのどこにでも作ることができますね。で、わざわざ更新しなくても、プログラムを終了すると勝手に釘付けになる

このようなタイマーの数は、あなたの想像力次第です。スプライトを動かしたくて、画面の左端から右端に這い上がって自殺する、いわば完全な自律性を持ったオブジェクトを作りました

...例を書くのが面倒、面白くない

 
Igor Makanu:

https://www.mql5.com/ru/forum/325418/page4#comment_16116740

このコードの値....ダイナミック・オブジェクトを作成することができます。で、わざわざアップデートしなくても、プログラムを終了すると勝手に釘付けになる

このようなタイマーの数は、あなたの想像力次第です。スプライトを動かしたくて、画面の左端から右端に這い上がって自殺する、いわば完全な自律性を持ったオブジェクトを作りました

...例を書くのが面倒くさい、面白くもない仕事

ああ、ざっと見た感じでは、

virtual void 0;
virtual void 0;
 
Nikolai Semko:

ええ、ざっと見ましたが、
、その点がよくわかりませんでした。

なぜ今そのようなコードになっているのか分かりませんが、そうなるはずです。

 virtual void OnInit() =0;
 virtual void OnTick() =0;
 virtual void OnDeinit( const int )=0;

が、タイマーにはこれらのメソッドは必要ないのでは、と思います。

ZS: オブジェクトは、このように自らを殺すことができます。

delete &this;
 
Igor Makanu:

なぜそのようなコードになるのか分かりませんが、そうなるはずです。

が、タイマーにはこれらのメソッドは必要ないのでは、と思います。

ZS: オブジェクトは、こんな風に自分を殺すことができます。

あなたと@fxsaberの おかげで、手に入れました。貯金箱に貯めた。

しかし、当然ながら、このコードには私の疑問に対する答えはない。

理由: