Erreurs, bugs, questions - page 2657

 

Ouais, c'est ma faute. Mais la question suivante se pose alors. Ce code C++ fonctionne (déjà exactement comme il faut ;-)).

class Base
{
  public:
    virtual void method1(void) { cout << "2\n"; }
};

class Derived: public Base
{
  public:
    virtual void method1(void) override { cout << "3\n"; }
};

template<typename T>
class Wrapper
{
  public:
    Wrapper(T *ptr)
    {
      ptr->T::method1();
    }
};

int main()
{
  Derived d;
  d.Base::method1();   // ok
  Wrapper<Base> w(&d); // ok

  return 0;
}

MQL similaire donne une erreur :

class Base
{
  public:
    virtual void method1(void) { Print(__FUNCSIG__); }
};

class Derived: public Base
{
  public:
    virtual void method1(void) override { Print(__FUNCSIG__); }
};

template<typename T>
class Wrapper
{
  public:
    Wrapper(T *ptr)
    {
      ptr.T::method1(); // <<< 'Base' is not a class, struct or union
    }
};


void OnStart()
{
  Derived d;
  d.Base::method1();   // ok
  Wrapper<Base> w(&d); // causes the error above
 
Stanislav Korotky:

Ouais, c'est ma faute. Mais la question suivante se pose alors. Ce code C++ fonctionne (déjà exactement comme il faut ;-)).

Un MQL similaire donne une erreur :

Je ne connais pas la tâche, mais je pense que vous cherchez quelque chose comme ça :

typedef void(*PTR)(void);

en MQL, il s'agit d'un pointeur vers une fonction void func(void)

dans une classe, vous pouvez déclarer un champ de type PTR, puis lui attribuer une fonction, et ensuite "déréférencer le pointeur" et appeler la fonction

Passer des fonctions écrites en style procédural dans la classe fonctionne sans aucun problème, les méthodes de la classe ne peuvent probablement pas être passées aussi facilement, vous pouvez essayer d'utiliser dynamic_cast, mais le code deviendra très confus.

 
Igor Makanu:

Je ne connais pas la tâche, mais je pense que vous cherchez quelque chose comme ça :

en MQL, c'est un pointeur vers une fonction void func(void)

dans une classe, vous pouvez déclarer un champ de type PTR, lui affecter une fonction, puis "déréférencer le pointeur" et appeler la fonction

Passer des fonctions écrites en style procédural dans la classe fonctionne sans aucun problème, les méthodes de la classe ne peuvent probablement pas être passées aussi facilement, vous pouvez essayer d'utiliser dynamic_cast, mais le code deviendra très confus.

typedef ne fonctionnera pas avec une méthode.

dynamic_cast fonctionne vers l'héritier (chaîne plus longue), c'est-à-dire que si le pointeur vers la base contient un dérivé, alors vous pouvez faire un cast vers le dérivé et s'il n'est pas NULL (i.e. cast normal), appeler sa méthode. Mais lorsque la situation est opposée, comme dans mon cas, il y a un pointeur vers le dérivé, alors il est par définition également de base. Et toute invocation de sa méthode virtuelle découvre que le dérivé est "assis" dans le pointeur et appelle l'implémentation surchargée. La base est nécessaire.

Il existe la construction syntaxique mentionnée ci-dessus en C++ à cette fin, mais MQL n'est pas C++. Apparemment, il n'y a pas encore de moyen de le faire.

J'ai trouvé une solution de contournement mais elle peut ne pas fonctionner dans toutes les tâches.

L'objectif de cette danse du tambourin, comme toujours, est de garder le code enchevêtré dans la "bibliothèque" et de rendre le code qui l'utilise clair et simple.

 

Avec quoi initialiser rand() dans le testeur ?

code :

input ulong param = 18446744073709551615;
void OnTick()
   {
   }
//+------------------------------------------------------------------+
double OnTester()
   {
      srand(GetTickCount()); 
      return(rand());
   }
//+------------------------------------------------------------------+

Je n'aime pas vraiment ce genre de génération pseudo-aléatoire :


 
Igor Makanu:

Avec quoi initialiser rand() dans le testeur ?

code :

Je n'aime pas vraiment ce genre de génération pseudo-aléatoire :


Aide :MathRand

Note

Avant d'appeler la fonction pour la première fois, vous devez utiliserMathSrand pour définir le générateur de nombres pseudo-aléatoires à l'état initial.


Essayez-le maintenant avec MathSrand.

Документация по MQL5: Математические функции / MathRand
Документация по MQL5: Математические функции / MathRand
  • www.mql5.com
Математические функции / MathRand - справочник по языку алгоритмического/автоматического трейдинга для MetaTrader 5
 
Vladimir Karputov:

Référence :MathRand

Note

La fonctionMathSrand doit être utilisée avant le premier appel de fonction pour placer le générateur de nombres pseudo-aléatoires à l'état initial.

Merci Cap !

Nous parlons du testeur.

ce code ne fonctionne pas non plus dans le testeur

input ulong param = 18446744073709551615;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
   {
   MathSrand(GetTickCount()); 
   return(INIT_SUCCEEDED);
   }
//+------------------------------------------------------------------+
void OnTick()
   {
   }
//+------------------------------------------------------------------+
double OnTester()
   {
      return(rand());
   }
//+------------------------------------------------------------------+
 
Igor Makanu:

Je pense que, pour un testeur, il n'est pas nécessaire d'utiliser MathSrand.

Mais si cela n'aide pas, alors il est fort probable que le testeur force MathSrand(GetTickCount()) à un moment donné.

Essayez ensuite MathSrand(int(GetMicrosecondCount()%1000000)) ;

Rappelez-vous, GetTickCount() change sa valeur toutes les 15,625 millisecondes. C'est un intervalle de temps très long pour un testeur.

 
Nikolai Semko:

Je pense que, pour un testeur, il n'est pas nécessaire d'utiliser MathSrand.

ceci est en contradiction avec la documentationhttps://www.mql5.com/ru/docs/math/mathrand

Avant le premier appel de fonction, vous devez utiliser la fonction MathSrand pour définir le générateur de nombres pseudo-aléatoires à l'état initial.

Je n'ai pas envie de parcourir le code source, mais pour les paquets de réseaux neuronaux, l'initialisation par une valeur aléatoire des poids NS est obligatoire, je soupçonne que cela a été fait conformément au matériel d'aide MQL - c'est-à-dire que srand() a été utilisé.

c'est-à-dire que l'utilisation de programmes MQL dans le testeur avec ce paquet NS se fera très probablement sur un seul cœur de processeur - les poids NS initiaux auront les mêmes valeurs, n'est-ce pas ?

c'est encore plus cool sans srand()

int OnInit()
   {
   return(INIT_SUCCEEDED);
   }
//+------------------------------------------------------------------+
void OnTick()
   {
   }
//+------------------------------------------------------------------+
double OnTester()
   {
      return(rand());
   }
//+------------------------------------------------------------------+
 
Igor Makanu:

cela contredit la documentationhttps://www.mql5.com/ru/docs/math/mathrand

Je ne veux pas regarder le code source, mais pour les paquets de réseaux neuronaux, l'initialisation par une valeur aléatoire des poids NS est obligatoire, je soupçonne que cela a été fait selon le matériel d'aide MQL - c'est-à-dire que srand() a été utilisé.

c'est-à-dire que l'utilisation de programmes MQL dans le testeur avec ce paquet NS se fera très probablement sur un seul cœur de processeur - les poids NS initiaux auront les mêmes valeurs, n'est-ce pas ?

encore plus drôle sans srand()

Igor, alors essayez MathSrand(int(GetMicrosecondCount()%16384)) ;

Je me demande comment l'image va changer.

 
Nikolai Semko:

Igor, essayez donc MathSrand(int(GetMicrosecondCount()%16384)) ;

Je me demande comment l'image va changer

int OnInit()
   {
   MathSrand(int(GetMicrosecondCount()%16384));   
   return(INIT_SUCCEEDED);
   }
//+------------------------------------------------------------------+
void OnTick()
   {
   }
//+------------------------------------------------------------------+
double OnTester()
   {
      return(rand());
   }
//+------------------------------------------------------------------+