Caractéristiques du langage mql5, subtilités et techniques - page 188

 
Nikolai Semko:
La question est de savoir comment vous pouvez lancer une méthode de classe non statique par un pointeur même si l'objet de l'autre classe (dans ce cas CTimer) est une propriété (variable) de la classe.

no.... Bien sûr, vous pouvez passer un pointeur à un autre objet et changer le pointeur là pour appeler la méthode.... mais vous devez connaître le nom de la méthode.

ZS : mais j'ai écrit hier, utiliser un exemple@fxsaber et hériter, dans chaque classe sera appelé par OnTimer , il y aura seulement une classe de base dans la boucle pour vérifier quel timer a quel intervalle de temps, et le lancement du timer principal dans la méthode statique mettre en œuvre

 
Nikolai Semko:
La question est de savoir comment vous pouvez utiliser un pointeur pour exécuter une méthode non statique d'une classe même si l'objet d'une autre classe (dans ce cas CTimer) est une propriété (variable) de cette classe. Est-ce possible ? J'ai bien peur que non.

- modèles

- les interfaces

 

des modèles :

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

Pas d'implémentation du timer lui-même ici, juste un exemple de comment appeler une fonction non-statique (écrit directement dans le forum, n'a pas vérifié)

 

Forum sur le trading, les systèmes de trading automatisé et les tests de stratégies de trading

MT5 et la vitesse en action

fxsaber, 2020.10.04 11:56

Détermine si un programme est en cours d'exécution sur une machine freinée ou non.

// Возвращает 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 question est de savoir comment exécuter une méthode de classe non statique par pointeur même si l'objet d'une autre classe (dans ce cas CTimer) est une propriété (variable) de cette classe. Et est-ce possible ? J'ai bien peur que non.

En termes généraux, cela ressemble à ceci :

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

Vous pouvez télécharger la librairie à partir d'ici : https://github.com/sva04091979/STD/tree/TimerEvent. Branche TimerEvent, pas encore fusionnée dans le master.

 
Igor Makanu:

no.... Bien sûr, vous pouvez passer un pointeur à un autre objet et changer le pointeur là pour appeler la méthode.... mais vous devez connaître le nom de la méthode.

ZS : mais j'ai écrit hier, utiliser un exemple@fxsaber et hériter, dans chaque classe sera appelé par OnTimer , il y aura seulement une classe de base dans la boucle pour vérifier quel timer a quel intervalle de temps, et le lancement du timer principal dans la méthode statique mettre en œuvre

Igor, je ne comprends pas de quel code fxsaber on parle.

Andrei Trukhanovich:

des modèles :

Il n'y a pas d'implémentation du timer lui-même, seulement un exemple de comment appeler une fonction non-statique (écrit directement sur le forum, je n'ai pas vérifié).

Merci. Je l'ai essayé. Rien ne sort.

Vladimir Simakov:

En général, ça ressemble à ça :

Vous pouvez télécharger la bibliothèque à partir d'ici : https://github.com/sva04091979/STD/tree/TimerEvent. La branche TimerEvent, je ne l'ai pas encore fusionnée dans le master.

Merci. Mais je n'ai pas non plus trouvé comment exécuter une méthode de classe non statique par le pointeur.


Merci à vous tous, mais peut-être n'ai-je pas formulé la tâche correctement ou n'ai-je pas trouvé de solution dans votre article en raison de mes connaissances limitées.
De quoi avez-vous besoin ?
Voici un exemple d'indicateur.
La méthode Timer4(marquée en bleu) de la classe CTestTimer est lancée par le pointeur de la classe CTimer(dans la boucle de la méthode CTimer:: OnTimer) passé à la classe CTimer::NewTimer au moment de l'exécution du constructeur lorsque l'objet de la classe CTestTimer est créé.
J'ai tout essayé. Il y a une impasse. Il est impossible d'obtenir un pointeur sur cette méthode. En C++, cela fonctionne de la manière suivante : typedef void (CTestTimer::*TFun)() ;
Et il y a une erreur étrange : 'Timer4' - pointer vers ce type de fonction n'est pas encore supporté ('Timer4' - pointer vers ce type de fonction n'est pas encore supporté)
"Pour l'instant" - comme si MQ avait mis cette question de côté en attendant des temps meilleurs.

#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()));
}
//+------------------------------------------------------------------+
Il semble qu'il n'y ait pas de solution à ce problème dans l'état actuel du langage MQL5.
 
Nikolai Semko:

Igor, je ne comprends pas de quel code fxsaber il s'agit.

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

la valeur de ce code est.... vous pouvez créer votre propre objet dynamique n'importe où dans le code -.... et ne prenez pas la peine de le mettre à jour, et il sera cloué tout seul lorsque vous quitterez le programme

le nombre de ces minuteurs n'est limité que par votre imagination... Je voulais déplacer un sprite - j'ai créé un objet qui a rampé du bord gauche de l'écran vers la droite et s'est tué - pour ainsi dire, une autonomie complète.

...trop paresseux pour écrire un exemple, tâche peu intéressante

 
Igor Makanu:

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

la valeur de ce code.... Vous pouvez créer votre propre objet dynamique.... n'importe où dans le code. et ne prenez pas la peine de le mettre à jour et quand vous quitterez le programme, il sera cloué par lui-même

le nombre de ces minuteurs n'est limité que par votre imagination... Je voulais déplacer un sprite - j'ai créé un objet qui a rampé du bord gauche de l'écran vers la droite et s'est tué - pour ainsi dire, une autonomie complète.

...trop paresseux pour écrire un exemple, tâche peu intéressante

Oui, j'ai jeté un coup d'oeil rapide.
n'a pas compris.

virtual void 0;
virtual void 0;
 
Nikolai Semko:

Oui, j'y ai jeté un coup d'oeil rapide.
n'a pas compris ce point.

Je ne sais pas pourquoi le code ressemble à ça maintenant, mais il devrait l'être :

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

mais vous n'avez pas besoin de ces méthodes pour la minuterie, à mon avis.

ZS : l'objet peut se tuer lui-même comme ceci

delete &this;
 
Igor Makanu:

Je ne sais pas pourquoi le code est comme ça, mais il devrait l'être :

mais vous n'avez pas besoin de ces méthodes pour la minuterie, à mon avis.

L'objet peut se tuer lui-même comme ceci

Je l'ai eu, grâce à vous et @fxsaber. Je l'ai gardé dans ma tirelire.

Mais, bien sûr, il n'y a pas de réponse à ma question dans ce code.

Raison: