Особенности языка mql5, тонкости и приёмы работы - страница 188

 
Nikolai Semko:
Вопрос в том, как по указателю запустить нестатический метод класса, даже если объект другого класса (в данном случае CTimer) является свойством(переменной) этого класса. 

нельзя.... можно конечно передать указатель на другой обьект и там разименовать указатель для вызова метода....но нужно имя метода знать, имхо путанная система получится 

ЗЫ: но писал же вчера, используйте пример @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);
}

Либу качаем отсюда: https://github.com/sva04091979/STD/tree/TimerEvent. Ветка TimerEvent, в master еще не сливал.

 
Igor Makanu:

нельзя.... можно конечно передать указатель на другой обьект и там разименовать указатель для вызова метода....но нужно имя метода знать, имхо путанная система получится 

ЗЫ: но писал же вчера, используйте пример @fxsaber и наследуйтесь, в каждом классе будет вызываться OnTimer , там останется только в базовом классе в цикле проверять у какого таймера какой интервал таймера стоит, а запуск основного таймера в статик методе осуществите

Игорь, не понял о каком коде fxsaber идет речь

Andrei Trukhanovich:

шаблоны:

здесь нет реализации самого таймера, только пример как вызвать нестатическую функцию (писал прямо на форуме, не проверял)

Спасибо. Пробовал. Ничего не выходит.

Vladimir Simakov:

В общем виде, как-то так видится:

Либу качаем отсюда: https://github.com/sva04091979/STD/tree/TimerEvent. Ветка TimerEvent, в master еще не сливал.

Спасибо. Но тоже не нашел как по указателю запустить нестатический метод класса.


Спасибо всем, но я возможно непонятно сформулировал задачу или не увидел у вас решения в силу своей ограниченности.
Что требуется?
Вот пример индикатора.
Нужно чтобы запускался метод Timer4 (выделен синим цветом) класса CTestTimer по указателю из класса CTimer (в цикле метода CTimer::OnTimer), который передается в класс CTimer::NewTimer в момент выполнения конструктора при создании объекта класса CTestTimer. 
Все уже перепробовал. В тупике. Неужели нелься получить указатель на этот метод. В С++ это работает через:  typedef void (CTestTimer::*TFun)();
И ошибка какая то странная: 'Timer4' - pointer to this function type is not supported yet ('Timer4' - указатель на этот тип функции пока не поддерживается)
"Пока" - словно 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:

Игорь, не понял о каком коде 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;

но для таймера эти методы не нужны, имхо

ЗЫ: самоубиться обьект может так

delete &this;
 
Igor Makanu:

не знаю почему так выглядит сейчас код, но должно было быть так:

но для таймера эти методы не нужны, имхо

ЗЫ: самоубиться обьект может так

понял, спасибо тебе и @fxsaber. Сохранил себе в копилку.

Но, конечно, ответа нет в этом коде на мой вопрос.