Questions sur la POO dans MQL5 - page 46

 
Igor Makanu:

c'est exactement ce dont je me suis éloigné, et c'est ce que j'ai fait au début

avec cette approche - hériter d'une classe de base, "où tout se trouve" - tout fonctionne, mais jusqu'à ce que nous voulions essayer de faire plusieurs champs de classe, et ensuite nous voulons ajouter plus de champs dans chaque classe de champ, et clouer le tout avec un tableau dynamique de classes

et ensuite nous obtiendrons que nous ne pouvons pas implémenter la méthode Save(int hndl) elle-même dans une classe de base - cette méthode sera en fait une interface, qui, comme discuté ci-dessus, ne sera pas du tout nécessaire - vous pouvez l'écrire sans interfaces

j'ai l'habitude de maximiser mes efforts sur la flexibilité du code - un minimum d'agitation - le résultat est un nouveau problème résolu, que ma terminologie soit pardonnée))))


le problème sera que, lors de la mise en œuvre de l'enregistrement dans un fichier, vous devezélaborer l'en-tête du fichier, qui doit décrire la quantité totale de différents types d'entrées et ensuite vous devez ne pas perdre la logique / l'ordre de l'enregistrement des données, afin de tout lire correctement..... et la finale sera si vous changez même un seul champ dans une classe

à mon avis, la difficulté d'un héritage aussi "facile" à partir d'une classe de base se résume au développement et à la maintenance d'une petite base de données, à la surveillance constante des modifications apportées à chaque classe.

public:
 void CBase::Save(...){
    SaveHeard(...);
    _Save(...)}
virtual void SaveHeard(...){...}

protected:
   void _Save(...){
       CBase::_Save(...);
       ...}

Quelque chose comme ceci : ))))

 
Vladimir Simakov:

Quelque chose comme ceci : ))))

Je comprends tout cela, mais au vieil adage "MQL n'est pas C", on ne peut qu'ajouter qu'il est insensé de compter sur un code bien structuré par tâches - les tâches MQL sont toujours hautement spécialisées et la réutilisation d'un gros code n'est souvent pas efficace.

HH : à mon avis, le principal objectif du code MQL est d'être aussi rapide que possible, pour être utilisé dans le testeur ou pour exécuter le code en un tick - sans perdre de ticks, tout est clair, mais il y a quelques restrictions - vous ne pouvez pas ignorer les pannes de connexion et le redémarrage du PC / terminal, et il s'agit de trouver l'optimum, pas seulementun codeagréable et structuré

 
Igor Makanu:

2. existe-t-il un moyen de décrire l'opérateur= et d'utiliser l'opérateur de copie natif ? .... c'est-à-dire un moyen d'appeler : :=

il existe un moyen, et comme d'habitude la solution est simple :

struct SMatrix
{
   struct SMATRIX{
   SMATRIX(){}
   struct SRow{int COL[];};
   SRow ROW[];
   };
   SMATRIX MATRIX;
   SMatrix(){}
   SMatrix(const int rows,const int cols){ this.Resize(rows,cols); }
   void Resize(const int rows,const int cols){ ArrayResize(this.MATRIX.ROW,rows); for(int i=0;i<rows; i++){ ArrayResize(this.MATRIX.ROW[i].COL,cols); }}
   void Free() { for(int i=0;i<ArraySize(this.MATRIX.ROW[i].COL); i++){ ArrayFree(this.MATRIX.ROW[i].COL); } ArrayFree(this.MATRIX.ROW);}
   int RowCount()const { return(ArraySize(this.MATRIX.ROW)); }
   int ColCount()const { if(this.RowCount()>0) return(ArraySize(this.MATRIX.ROW[0].COL)); else return(0); }
   void operator=(const SMatrix &v) { this.Resize(v.RowCount(),v.ColCount()); this.MATRIX = v.MATRIX;}

};

//+------------------------------------------------------------------+
void OnStart()
{
   SMatrix A(2, 5);
   int count = 0;
   for(int i = 0; i < A.RowCount(); i++)
      for(int j = 0; j < A.ColCount(); j++)
         A.MATRIX.ROW[i].COL[j] = count++;
   
   SMatrix C(5, 2);
   count = 100;
   for(int i = 0; i < C.RowCount(); i++)
      for(int j = 0; j < C.ColCount(); j++)
         C.MATRIX.ROW[i].COL[j] = count++;

   
   SMatrix B = A;
   for(int i = 0; i < B.RowCount(); i++)
      ArrayPrint(B.MATRIX.ROW[i].COL);
   
   B = C;
   for(int i = 0; i < B.RowCount(); i++)
      ArrayPrint(B.MATRIX.ROW[i].COL);
   
}

nous initialisons la matrice A, puis C

nous assignons d'abord une nouvelle matrice B = A et la désinitialisons, puis B = C et la désinitialisons.

2020.04.21 00:35:50.559 tst (EURUSD,H1) 0 1 2 3 4

2020.04.21 00:35:50.559 tst (EURUSD,H1) 5 6 7 8 9

2020.04.21 00:35:50.560 tst (EURUSD,H1) 100 101

2020.04.21 00:35:50.560 tst (EURUSD,H1) 102 103

2020.04.21 00:35:50.560 tst (EURUSD,H1) 104 105

2020.04.21 00:35:50.560 tst (EURUSD,H1) 106 107

2020.04.21 00:35:50.560 tst (EURUSD,H1) 108 109

le point - vous devez envelopper la structure dans la structure et encore dans la structure.... excusez mon terme technique ))))


SZY : la solution est bonne, nous devrions remplacer les méthodes RowCount() et ColCount() par des champs de structure RowCount et ColCount(), pour faire moins d'appels... Mais dans l'ensemble, il fonctionne comme je le voulais.

 
Vous êtes sérieux ?
 
Алексей Тарабанов:
Vous êtes sérieux ?

Quel est le problème, l'homme a résolu ce problème depuis 2012, ne le dérangez pas, il sait mieux que quiconque.

 
Sergey Dzyublik:

Quel est le problème, l'homme a résolu ce problème depuis 2012, ne le dérangez pas, il sait mieux que quiconque.

Vous pensez à plat.

la tâche consiste à connaître les capacités techniques du langage MQL, de sorte qu'un tel exemplehttps://docs.microsoft.com/en-us/archive/msdn-magazine/2018/april/test-run-understanding-lstm-cells-using-csharp.

peut être porté "directement" - cette tâche a été résolue maintenant, en portant toutes les fonctions de l'exemple un-à-un avec une seule hypothèse : float[][] result --> SMatrix result

 
Igor Makanu:

il existe un moyen, et comme d'habitude la solution est simple :

initialiser la matrice A, puis C

d'abord assigner une nouvelle matrice B = A et désinitialiser, puis B = C et désinitialiser


HH : la solution est bonne, nous devons remplacer les méthodes RowCount() et ColCount() par des champs de structure RowCount et ColCount() pour faire moins d'appels ... Mais dans l'ensemble, tout fonctionne comme je le voulais.

Malheureusement, tout n'est pas aussi heureux que nous l'aurions souhaité. Dans MQL, il y a un bogue de longue date avec la copie de tableaux par l'opérateur de copie par défaut. Seul ArrayCopy des éléments d'un tableau dans un autre a lieu. La taille du tableau résultant n'est pas synchronisée avec la source (elle n'est pas tronquée). Cela signifie que si A(10) et B(20) ont été utilisés, après B=A, vous obtiendrez également B(20), c'est-à-dire que la moitié des éléments seront remplacés par des éléments de A, le reste restera inchangé. Bien entendu, ce n'est pas du tout ce que l'on attend de l'opérateur=. C'est pourquoi nous devrons écrire notre propre opérateur pour les tableaux.

Je dois admettre que je pensais que ce bug avait déjà été corrigé. Mais j'ai vérifié et c'est toujours là.

 
Alexey Navoykov:

Malheureusement, tout n'est pas aussi heureux que nous le voudrions. MQL a un bogue de longue date avec la copie de tableaux en utilisant l'opérateur de copie par défaut. Seul ArrayCopy des éléments d'un tableau à l'autre se produit. La taille du tableau résultant n'est pas synchronisée avec la source (il n'est pas tronqué). Cela signifie que si A(10) et B(20) étaient présents, après B=A vous obtiendrez également B(20), c'est-à-dire que la moitié des éléments seront remplacés par des éléments de A, le reste restera inchangé. Bien entendu, ce n'est pas du tout ce que l'on attend de l'opérateur=. C'est pourquoi nous devrons écrire notre propre opérateur pour les tableaux.

Je dois avouer que je pensais que ce bug avait déjà été corrigé. Mais je l'ai vérifié et il est toujours là.

La punaise a été récemment rappelée :

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

Questions sur la POO dans MQL5

Sergey Dzyublik, 2020.04.18 17:48

Ensuite, selon votre terminologie, l'appel de l'opérateur d'affectation par défaut peut donner un "type de données incomplet".
Bug de 2019.05.03 jamais corrigé: https://www.mql5.com/ru/forum/1111/page2451#comment_11556395


La ligne donnée est censée contourner le bogue :

struct SMatrix
{
   struct SMATRIX{
   SMATRIX(){}
   struct SRow{int COL[];};
   SRow ROW[];
   };
   SMATRIX MATRIX;
   SMatrix(){}
   SMatrix(const int rows,const int cols){ this.Resize(rows,cols); }
   void Resize(const int rows,const int cols){ ArrayResize(this.MATRIX.ROW,rows); for(int i=0;i<rows; i++){ ArrayResize(this.MATRIX.ROW[i].COL,cols); }}
   void Free() { for(int i=0;i<ArraySize(this.MATRIX.ROW[i].COL); i++){ ArrayFree(this.MATRIX.ROW[i].COL); } ArrayFree(this.MATRIX.ROW);}
   int RowCount()const { return(ArraySize(this.MATRIX.ROW)); }
   int ColCount()const { if(this.RowCount()>0) return(ArraySize(this.MATRIX.ROW[0].COL)); else return(0); }
   void operator=(const SMatrix &v) { this.Resize(v.RowCount(),v.ColCount()); this.MATRIX = v.MATRIX;}

};
 
Sergey Dzyublik:

La ligne donnée devrait contourner le bogue :

Oh, oui, je ne l'ai pas remarqué au début... Mais alors vous auriez pu écrire ArrayCopy tout de suite. Pourquoi avons-nous besoin de ce joint SMATRIX du tout alors ....

 
Alexey Navoykov:

Oh, oui, je ne l'ai pas remarqué au début... Mais vous auriez pu écrire ArrayCopy tout de suite. Pourquoi avons-nous besoin de ce pavé SMATRIX ?...

МТ les développeurs écrivent toujours que l'utilisation de mécanismes intégrés au compilateur sera plus rapide même que l'appel de fonctions standard.

Si vous avez le temps et l'intérêt, vérifiez la vitesse de ma version et de la vôtre avec ArrayCopy

Je vérifierai la vitesse un peu plus tard, je suis au milieu d'une leçon.

Raison: