Merkmale der Sprache mql5, Feinheiten und Techniken - Seite 188

 
Nikolai Semko:
Die Frage ist, wie man eine nicht statische Methode einer Klasse durch einen Zeiger starten kann, auch wenn das Objekt einer anderen Klasse (in unserem Fall CTimer) eine Eigenschaft (Variable) der Klasse ist.

nein.... Sie können natürlich einen Zeiger auf ein anderes Objekt übergeben und den Zeiger dort ändern, um die Methode .... aufzurufen, aber Sie müssen den Namen der Methode kennen.

ZS: aber schrieb gestern, verwenden Sie ein Beispiel@fxsaber und erben, in jeder Klasse wird von OnTimer aufgerufen werden, wird es nur eine Basisklasse in der Schleife zu überprüfen, welche Timer hat, was Timer-Intervall, und der Start des Haupt-Timer in statische Methode zu implementieren

 
Nikolai Semko:
Die Frage ist, wie man einen Zeiger verwenden kann, um eine nicht-statische Methode einer Klasse auszuführen, auch wenn das Objekt einer anderen Klasse (in diesem Fall CTimer) eine Eigenschaft (Variable) dieser Klasse ist. Ist das möglich? Ich fürchte, nein.

- Vorlagen

- Schnittstellen

 

Vorlagen:

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;
}

Keine Implementierung des Timers selbst hier, nur ein Beispiel, wie man eine nicht-statische Funktion aufruft (schrieb direkt im Forum, habe nicht überprüft)

 

Forum zum Thema Handel, automatisierte Handelssysteme und Testen von Handelsstrategien

MT5 und Geschwindigkeit in Aktion

fxsaber, 2020.10.04 11:56

Ermittelt, ob ein Programm auf einer gebremsten Maschine läuft oder nicht.

// Возвращает 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:
Die Frage ist, wie eine nicht-statische Klassenmethode per Zeiger ausgeführt werden kann, auch wenn das Objekt einer anderen Klasse (in diesem Fall CTimer) eine Eigenschaft (Variable) dieser Klasse ist. Und ist das möglich? Ich fürchte, nein.

Allgemein ausgedrückt, sieht das so aus:

#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);
}

Sie können die Lib von hier herunterladen: https://github.com/sva04091979/STD/tree/TimerEvent. TimerEvent-Zweig, noch nicht in den Master-Zweig eingefügt.

 
Igor Makanu:

nein.... Sie können natürlich einen Zeiger auf ein anderes Objekt übergeben und den Zeiger dort ändern, um die Methode .... aufzurufen, aber Sie müssen den Namen der Methode kennen.

ZS: aber schrieb gestern, verwenden Sie ein Beispiel@fxsaber und erben, in jeder Klasse wird von OnTimer aufgerufen werden, wird es nur in der Basisklasse in der Schleife bleiben, um zu überprüfen, welche Timer hat, was Timer-Intervall, und der Start des Haupt-Timer in statische Methode implementieren

Igor, ich verstehe nicht, über welchen fxsaber-Code wir hier reden.

Andrei Trukhanovich:

Vorlagen:

Es gibt keine Implementierung des Timers selbst, nur ein Beispiel, wie man eine nicht-statische Funktion aufruft (schrieb direkt auf dem Forum, habe nicht überprüft)

Ich danke Ihnen. Ich habe es ausprobiert. Es kommt nichts heraus.

Vladimir Simakov:

Im Allgemeinen sieht es folgendermaßen aus:

Sie können die Bibliothek von hier herunterladen: https://github.com/sva04091979/STD/tree/TimerEvent. TimerEvent-Zweig, ich habe ihn noch nicht in den Master-Zweig eingefügt.

Ich danke Ihnen. Aber ich habe nicht gefunden, wie man eine nicht-statische Klasse Methode durch den Zeiger entweder laufen.


Vielen Dank an Sie alle, aber vielleicht habe ich die Aufgabe nicht richtig formuliert oder aufgrund meiner begrenzten Kenntnisse keine Lösung in Ihrem Artikel gefunden.
Was brauchen Sie?
Hier ist ein Beispiel für einen Indikator.
Die Methode Timer4(blau markiert) der Klasse CTestTimer wird durch den Zeiger von der Klasse CTimer(in der Schleife der Methode CTimer:: OnTimer) gestartet, der zum Zeitpunkt der Ausführung des Konstruktors an die Klasse CTimer::NewTimer übergeben wird, wenn das Objekt der Klasse CTestTimer erstellt wird.
Ich habe alles versucht. Es gibt eine Blockade. Es ist unmöglich, einen Zeiger auf diese Methode zu erhalten. In C++ funktioniert es durch: typedef void (CTestTimer::*TFun)();
Und es gibt einen seltsamen Fehler: 'Timer4' - Zeiger auf diesen Funktionstyp wird noch nicht unterstützt ('Timer4' - Zeiger auf diesen Funktionstyp wird noch nicht unterstützt)
"For now" - als ob MQ diese Frage bis zu besseren Zeiten beiseite legen würde.

#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()));
}
//+------------------------------------------------------------------+
Es scheint, dass es in der aktuellen Version der MQL5-Sprache keine Lösung für dieses Problem gibt
 
Nikolai Semko:

Igor, ich verstehe nicht, von welchem fxsaber-Code wir sprechen

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

der Wert dieses Codes lautet.... Nun, Sie können Ihr eigenes dynamisches Objekt überall im Code erstellen -.... und machen Sie sich nicht die Mühe, es zu aktualisieren, und es wird von selbst festgenagelt, wenn Sie das Programm beenden

die Anzahl solcher Zeitschaltuhren ist nur durch Ihre Vorstellungskraft begrenzt... Ich wollte ein Sprite bewegen - habe ein Objekt erstellt, das vom linken Rand des Bildschirms nach rechts kroch und sich selbst tötete - sozusagen völlige Autonomie

...zu faul, ein Beispiel zu schreiben, keine interessante Aufgabe

 
Igor Makanu:

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

den Wert dieses Codes.... Nun, Sie können Ihr eigenes dynamisches Objekt erstellen.... überall im Code und machen Sie sich nicht die Mühe, es zu aktualisieren, und wenn Sie das Programm beenden, wird es von selbst festgenagelt sein

die Anzahl solcher Zeitschaltuhren ist nur durch Ihre Vorstellungskraft begrenzt... Ich wollte ein Sprite bewegen - habe ein Objekt erstellt, das vom linken Rand des Bildschirms nach rechts kroch und sich selbst tötete - sozusagen völlige Autonomie

...zu faul, ein Beispiel zu schreiben, keine interessante Aufgabe

Ja, ich habe einen kurzen Blick darauf geworfen.
hat es nicht verstanden.

virtual void 0;
virtual void 0;
 
Nikolai Semko:

Ja, ich habe einen kurzen Blick darauf geworfen.
hat diesen Punkt nicht verstanden.

Ich weiß nicht, warum der Code jetzt so aussieht, aber es sollte so sein:

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

aber für den Timer braucht man diese Methoden nicht, imho.

ZS: Das Objekt kann sich auf diese Weise selbst töten

delete &this;
 
Igor Makanu:

Ich weiß nicht, warum der Code so aussieht, aber es sollte so sein:

aber für den Timer braucht man diese Methoden nicht, imho.

ZS: Das Objekt kann sich auf diese Weise selbst töten

Ich hab's, dank dir und @fxsaber. Ich habe es in meinem Sparschwein gespart.

Aber natürlich gibt es in diesem Code keine Antwort auf meine Frage.

Grund der Beschwerde: