Características da linguagem mql5, subtilezas e técnicas - página 188

 
Nikolai Semko:
A questão é como iniciar um método não estático de uma classe por um ponteiro, mesmo que o objecto de outra classe (CTimer no nosso caso) seja uma propriedade (variável) da classe.

no.... claro que pode passar um ponteiro para outro objecto e mudar o ponteiro para lá chamar método...., mas precisa de saber o nome do método.

ZS: mas escreveu ontem, use um exemplo@fxsaber e herde, em cada classe será chamada pelo OnTimer , haverá apenas uma classe base no laço para verificar que temporizador tem que intervalo de temporizador, e o lançamento do temporizador principal no implemento do método estático

 
Nikolai Semko:
A questão é como se pode utilizar um ponteiro para executar um método não estático de uma classe, mesmo que o objecto de outra classe (neste caso o CTimer) seja uma propriedade (variável) dessa classe. Será possível? Receio que não.

- modelos

- interfaces

 

modelos:

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

Nenhuma implementação do temporizador em si aqui, apenas um exemplo de como chamar uma função não estática (escrito directamente no fórum, não verificado)

 

Fórum sobre comércio, sistemas automatizados de comércio e testes de estratégia comercial

MT5 e Velocidade em Acção

fxsaber, 2020.10.04 11:56

Determina se um programa está ou não a funcionar numa máquina travada.

// Возвращает 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:
A questão é como executar um método de classe não estático por ponteiro mesmo que o objecto de outra classe (neste caso o CTimer) seja uma propriedade (variável) desta classe. E será isso possível? Receio que não.

Em termos gerais, é o que parece:

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

Pode descarregar a libra a partir daqui: https://github.com/sva04091979/STD/tree/TimerEvent. TimerEvent ramo, ainda não fundido no mestre.

 
Igor Makanu:

no.... claro que pode passar um ponteiro para outro objecto e mudar o ponteiro para lá chamar método...., mas precisa de saber o nome do método.

ZS: mas escreveu ontem, use um exemplo@fxsaber e herde, em cada classe será chamada pelo OnTimer, só permanecerá na classe base no laço para verificar qual temporizador tem qual intervalo de temporizador, e o lançamento do temporizador principal no implemento do método estático

Igor, não entendo de que código fxsaber estamos a falar

Andrei Trukhanovich:

modelos:

Não há implementação do temporizador em si, apenas um exemplo de como chamar uma função não estática (escrito directamente no fórum, não verificado)

Obrigado. Experimentei-o. Nada sai.

Vladimir Simakov:

Em geral, é o que parece:

Descarregue a biblioteca a partir daqui: https://github.com/sva04091979/STD/tree/TimerEvent. TimerEvent branch, ainda não o fundi no master.

Obrigado. Mas também ainda não descobri como executar um método de classe não estático através do ponteiro.


Graças a todos vós, mas talvez não tenha formulado a tarefa correctamente ou não tenha encontrado uma solução no vosso artigo devido ao meu conhecimento limitado.
De que é que precisa?
Aqui está um exemplo de um indicador.
O método Timer4(marcado a azul) da classe CTestTimer é lançado pelo ponteiro da classe CTimer(no laço do método CTimer:: OnTimer) passou para a classe CTimer::NewTimer no momento da execução do construtor, quando o objecto da classe CTestTimer é criado.
Tentei tudo. Há um impasse. Não há maneira de obter um ponteiro para este método. Em C++ funciona através de: typedef void (CTestTimer::*TFun)();
E há um estranho erro: 'Timer4' - ponteiro para este tipo de função ainda não é suportado ('Timer4' - ponteiro para este tipo de função ainda não é suportado)
"Por agora" - como se o MQ pusesse esta questão de lado até tempos melhores.

#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 não há solução para este problema no estado actual da linguagem MQL5
 
Nikolai Semko:

Igor, não entendo de que código fxsaber estamos a falar

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

o valor deste código é.... bem, pode criar o seu próprio objecto dinâmico em qualquer parte do código -.... e não se preocupe em actualizá-lo, e ele será pregado por si mesmo quando sair do programa

o número de tais temporizadores é limitado apenas pela sua imaginação. quer mover um duende - criar um objecto que se arrastou da extremidade esquerda do ecrã para a direita e se matou - autonomia completa, por assim dizer

...demasiado preguiçoso para escrever um exemplo, não é uma tarefa interessante

 
Igor Makanu:

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

o valor deste código.... bem, pode criar o seu próprio objecto dinâmico.... em qualquer parte do código e não se preocupe em actualizá-lo e quando sair do programa, ele será pregado por si

o número de tais temporizadores é limitado apenas pela sua imaginação. Queria mover um duende - criou um objecto que se arrastava da extremidade esquerda do ecrã para a direita e se matava - por assim dizer, total autonomia

...demasiado preguiçoso para escrever um exemplo, não é uma tarefa interessante

Sim, dei uma vista de olhos rápida.
não o consegui

virtual void 0;
virtual void 0;
 
Nikolai Semko:

Sim, dei uma vista de olhos rápida.
não compreendeu esse ponto.

Não sei porque é que o código é assim agora, mas deveria ser:

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

mas não precisa destes métodos para o temporizador, imho.

ZS: o objecto pode matar-se desta forma

delete &this;
 
Igor Makanu:

Não sei porque é que o código tem esse aspecto, mas deveria ter:

mas não precisa destes métodos para o temporizador, imho.

ZS: O objecto pode matar-se desta forma

Percebido, graças a si e ao @fxsaber. Guardei-o no meu mealheiro.

Mas, é claro, não há resposta à minha pergunta neste código.

Razão: