Caratteristiche del linguaggio mql5, sottigliezze e tecniche - pagina 188

 
Nikolai Semko:
La domanda è come si può avviare un metodo di classe non statico con un puntatore anche se l'oggetto di un'altra classe (in questo caso CTimer) è una proprietà (variabile) della classe.

no.... Naturalmente si può passare un puntatore a un altro oggetto e cambiare il puntatore lì per chiamare il metodo.... ma è necessario conoscere il nome del metodo.

ZS: ma ha scritto ieri, utilizzare un esempio@fxsaber ed ereditare, in ogni classe sarà chiamato da OnTimer , ci sarà solo una classe base nel ciclo per controllare quale timer ha quale intervallo di tempo, e il lancio del timer principale in metodo statico implementare

 
Nikolai Semko:
La domanda è come si può usare un puntatore per eseguire un metodo non statico di una classe anche se l'oggetto di un'altra classe (in questo caso CTimer) è una proprietà (variabile) di quella classe. È possibile? Temo di no.

- modelli

- interfacce

 

modelli:

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

Nessuna implementazione del timer stesso qui, solo un esempio di come chiamare una funzione non statica (scritto direttamente nel forum, non ho controllato)

 

Forum sul trading, sistemi di trading automatico e test di strategie di trading

MT5 e la velocità in azione

fxsaber, 2020.10.04 11:56

Determina se un programma è in esecuzione su una macchina frenata o meno.

// Возвращает 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:
La domanda è come eseguire un metodo di classe non statico tramite puntatore anche se l'oggetto di un'altra classe (in questo caso CTimer) è una proprietà (variabile) di questa classe. Ed è possibile? Temo di no.

In termini generali, si presenta così:

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

Potete scaricare la lib da qui: https://github.com/sva04091979/STD/tree/TimerEvent. Ramo TimerEvent, non ancora unito al master.

 
Igor Makanu:

no.... Naturalmente si può passare un puntatore a un altro oggetto e cambiare il puntatore lì per chiamare il metodo.... ma è necessario conoscere il nome del metodo.

ZS: ma ha scritto ieri, utilizzare un esempio@fxsaber ed ereditare, in ogni classe sarà chiamato da OnTimer , ci sarà solo una classe base nel ciclo per controllare quale timer ha quale intervallo di tempo, e il lancio del timer principale in metodo statico implementare

Igor, non capisco di quale codice fxsaber stiamo parlando

Andrei Trukhanovich:

modelli:

Non c'è un'implementazione del timer stesso, solo un esempio di come chiamare una funzione non statica (scritto direttamente sul forum, non ho controllato)

Grazie. Provato. Non esce niente.

Vladimir Simakov:

In generale, si presenta così:

Si scarica la libreria da qui: https://github.com/sva04091979/STD/tree/TimerEvent. TimerEvent, non l'ho ancora unito al master.

Grazie. Ma non ho nemmeno trovato come eseguire un metodo di classe non statico tramite il puntatore.


Grazie a tutti voi, ma forse non ho formulato correttamente il compito o non ho trovato una soluzione nel vostro articolo a causa della mia conoscenza limitata.
Di cosa avete bisogno?
Ecco un esempio di indicatore.
Il metodo Timer4(segnato in blu) della classe CTestTimer è lanciato dal puntatore della classe CTimer(nel ciclo del metodo CTimer:: OnTimer) passato alla classe CTimer::NewTimer al momento dell'esecuzione del costruttore quando viene creato l'oggetto della classe CTestTimer.
Ho provato di tutto. C'è una situazione di stallo. Non c'è modo di ottenere un puntatore a questo metodo. In C++ funziona attraverso: typedef void (CTestTimer::*TFun)();
E c'è uno strano errore: 'Timer4' - pointer to this function type is not supported yet ('Timer4' - pointer to this function type is not supported yet)
"For now" - come se MQ mettesse da parte questa domanda fino a tempi migliori.

#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()));
}
//+------------------------------------------------------------------+
Sembra che non ci sia una soluzione a questo problema nello stato attuale del linguaggio MQL5
 
Nikolai Semko:

Igor, non capisco di quale codice fxsaber stiamo parlando

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

il valore di questo codice è.... beh, potete creare il vostro oggetto dinamico in qualsiasi punto del codice -.... e non preoccupatevi di aggiornarlo, e sarà inchiodato da solo quando uscirete dal programma

il numero di questi timer è limitato solo dalla vostra immaginazione... Volevo spostare uno sprite - ho creato un oggetto che strisciava dal bordo sinistro dello schermo verso destra e si uccideva - per così dire, completa autonomia

...troppo pigro per scrivere un esempio, non è un compito interessante

 
Igor Makanu:

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

il valore di questo codice.... beh, potete creare il vostro oggetto dinamico.... ovunque nel codice e non preoccuparti di aggiornarlo e quando esci dal programma, sarà inchiodato da solo

il numero di questi timer è limitato solo dalla vostra immaginazione... Volevo spostare uno sprite - ho creato un oggetto che strisciava dal bordo sinistro dello schermo verso destra e si uccideva - per così dire, completa autonomia

...troppo pigro per scrivere un esempio, non è un compito interessante

Sì, ho dato un'occhiata veloce.
non ha capito

virtual void 0;
virtual void 0;
 
Nikolai Semko:

Sì, ho dato un'occhiata veloce.
non ha capito questo punto.

Non so perché il codice sia così ora, ma dovrebbe esserlo:

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

ma non avete bisogno di questi metodi per il timer, imho.

ZS: l'oggetto può uccidersi in questo modo

delete &this;
 
Igor Makanu:

Non so perché il codice sia così, ma dovrebbe esserlo:

ma non avete bisogno di questi metodi per il timer, imho.

ZS: L'oggetto può uccidersi in questo modo

Trovato, grazie a te e a @fxsaber. L'ho salvato nel mio salvadanaio.

Ma, ovviamente, non c'è nessuna risposta alla mia domanda in questo codice.