Características del lenguaje mql5, sutilezas y técnicas - página 188

 
Nikolai Semko:
La pregunta es cómo se puede iniciar un método no estático de una clase con un puntero aunque el objeto de otra clase (CTimer en nuestro caso) sea una propiedad (variable) de la clase.

no.... Por supuesto que puedes pasar un puntero a otro objeto y cambiar el puntero allí para llamar a method.... pero necesitas saber el nombre del método.

ZS: pero escribió ayer, utilizar un ejemplo@fxsaber y heredar, en cada clase será llamado por OnTimer , sólo habrá una clase base en el bucle para comprobar qué temporizador tiene qué intervalo de tiempo, y el lanzamiento del temporizador principal en el método estático implementar

 
Nikolai Semko:
La pregunta es cómo se puede utilizar un puntero para ejecutar un método no estático de una clase aunque el objeto de otra clase (en este caso CTimer) sea una propiedad (variable) de esa clase. ¿Es posible? Me temo que no.

- plantillas

- interfaces

 

plantillas:

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

No hay implementación del temporizador en sí, sólo un ejemplo de cómo llamar a una función no estática (escrito directamente en el foro, no lo comprobé)

 

Foro sobre trading, sistemas de trading automatizados y pruebas de estrategias de trading

MT5 y Speed en acción

fxsaber, 2020.10.04 11:56

Determina si un programa se está ejecutando en una máquina frenada o no.

// Возвращает 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 cuestión es cómo ejecutar un método de clase no estático por puntero aunque el objeto de otra clase (en este caso CTimer) sea una propiedad (variable) de esta clase. ¿Y es posible? Me temo que no.

En términos generales, es así:

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

Puedes descargar la librería desde aquí: https://github.com/sva04091979/STD/tree/TimerEvent. Rama TimerEvent, aún no fusionada con el master.

 
Igor Makanu:

no.... Por supuesto que puedes pasar un puntero a otro objeto y cambiar el puntero allí para llamar a method.... pero necesitas saber el nombre del método.

ZS: pero escribió ayer, utilizar un ejemplo@fxsaber y heredar, en cada clase será llamado por OnTimer , sólo habrá una clase base en el bucle para comprobar qué temporizador tiene qué intervalo de tiempo, y el lanzamiento del temporizador principal en el método estático implementar

Igor, no entiendo de qué código fxsaber estamos hablando

Andrei Trukhanovich:

plantillas:

No hay ninguna implementación del temporizador en sí, sólo un ejemplo de cómo llamar a una función no estática (escrito directamente en el foro, no lo he comprobado)

Gracias. Lo he probado. No sale nada.

Vladimir Simakov:

En general, se ve así:

La biblioteca puede descargarse desde aquí: https://github.com/sva04091979/STD/tree/TimerEvent. La rama TimerEvent, aún no la he fusionado en el master.

Gracias. Pero tampoco he encontrado cómo ejecutar un método de clase no estático por el puntero.


Gracias a todos, pero quizás no he redactado bien la tarea o no he encontrado una solución en su artículo debido a mis escasos conocimientos.
¿Qué necesitas?
Este es un ejemplo de indicador.
El método Timer4(marcado en azul) de la clase CTestTimer es lanzado por el puntero de la clase CTimer(en el bucle del método CTimer:: OnTimer) pasado a la clase CTimer::NewTimer en el momento de la ejecución del constructor cuando se crea el objeto de la clase CTestTimer.
He probado todo. Hay un punto muerto. No hay manera de obtener un puntero a este método. En C++ funciona a través de: typedef void (CTestTimer::*TFun)();
Y hay un extraño error: 'Timer4' - po inter to this function type is not supported yet ('Timer4' - pointer to this function type is not supported yet)
"Por ahora" - como si MQ dejara esta cuestión de lado hasta mejores tiempos.

#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()));
}
//+------------------------------------------------------------------+
Parece que no hay solución a este problema en el estado actual del lenguaje MQL5
 
Nikolai Semko:

Igor, no entiendo de qué código fxsaber estamos hablando

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

el valor de este código es.... bueno, puedes crear tu propio objeto dinámico en cualquier parte del código -.... y no te molestes en actualizarla, y se clavará sola cuando salgas del programa

el número de estos temporizadores sólo está limitado por su imaginación... Quería mover un sprite - creó un objeto que se arrastró desde el borde izquierdo de la pantalla a la derecha y se suicidó - por así decirlo, completa autonomía

...demasiado perezoso para escribir un ejemplo, no es una tarea interesante

 
Igor Makanu:

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

el valor de este código.... bueno, puedes crear tu propio objeto dinámico.... en cualquier parte del código y no te molestes en actualizarlo y cuando salgas del programa, se clavará solo

el número de estos temporizadores sólo está limitado por su imaginación... Quería mover un sprite - creó un objeto que se arrastró desde el borde izquierdo de la pantalla a la derecha y se suicidó - por así decirlo, completa autonomía

...demasiado perezoso para escribir un ejemplo, no es una tarea interesante

Sí, le eché un vistazo rápido.
no lo entendió

virtual void 0;
virtual void 0;
 
Nikolai Semko:

Sí, le eché un vistazo rápido.
no entendió ese punto.

No sé por qué el código se ve así ahora, pero debería ser así:

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

pero no necesitas estos métodos para el temporizador, imho.

ZS: el objeto puede suicidarse así

delete &this;
 
Igor Makanu:

No sé por qué el código se ve así, pero debería ser así:

pero no necesitas estos métodos para el temporizador, imho.

ZS: El objeto puede suicidarse así

Lo tengo, gracias a ti y a @fxsaber. Lo he guardado en mi hucha.

Pero, por supuesto, no hay respuesta a mi pregunta en este código.