mql5语言的特点、微妙之处以及技巧 - 页 188

 
Nikolai Semko:
问题是,即使其他类的对象(在我们的例子中是CTimer)是该类的一个属性(变量),你如何用一个指针启动一个 的非静态方法

no....当然,你可以传递一个指针到另一个对象,并改变那里的指针来调用method....,但你需要知道这个方法的名称。

ZS:但是昨天写了一个例子,用@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分支,尚未合并到主分支。

 
Igor Makanu:

no....当然,你可以传递一个指针到另一个对象,并改变那里的指针来调用method....,但你需要知道这个方法的名称。

ZS:但是昨天写了一个例子,用@fxsaber 来继承,在每个类中都会调用OnTimer,在基类中只会有一个循环来检查哪个定时器有什么定时间隔,而启动主定时器的静态方法实现

伊戈尔,我不明白我们在谈论什么fxsaber代码

Andrei Trukhanovich:

模板。

没有计时器本身的实现,只有一个如何调用非静态函数的例子(在论坛上直接写的,没检查)。

谢谢你。试过了。没有任何东西出来。

Vladimir Simakov:

一般来说,它看起来像这样。

你可以从这里下载该库:https://github.com/sva04091979/STD/tree/TimerEvent。 TimerEvent分支,我还没有把它合并到主分支。

谢谢你。但我也没有找到如何通过指针运行非静态类方法。


谢谢大家,但也许我没有正确地表述任务,或者由于我的知识有限,没有在你们的文章中看到解决方案。
你需要什么?
下面是一个指标的例子。
CTestTimer类的Timer4方法(标记为蓝色) 是由CTimer 类的指针(在CTimer:: OnTimer方法的循环中)传递给CTimer::NewTimer类的,当CTestTimer类的对象被创建时,在构造函数执行的时刻启动的。
,我试了所有的方法。出现了一个僵局。没有办法获得这个方法的指针。在C++中,它通过以下方式工作:typedef void (CTestTimer::*TFun)();
而且有一个奇怪的错误:'Timer4' - 指向此函数类型的指针还不被支持('Timer4' - 指向此函数类型的指针还不被支持)
"For now" - 仿佛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;

但我认为,你不需要用这些方法来做定时器。

ZS:该物体可以像这样杀死自己

delete &this;
 
Igor Makanu:

我不知道为什么代码看起来像这样,但它应该是这样。

但我认为,你不需要用这些方法来做定时器。

ZS: 物体可以像这样杀死自己

找到了,感谢你和@fxsaber。把它保存在我的储蓄银行里。

但是,当然,这段代码中没有对我的问题的答案。