Domande su OOP in MQL5 - pagina 46

 
Igor Makanu:

Questo è esattamente quello da cui mi sono allontanato, ed è quello che ho fatto all'inizio

con questo approccio - ereditare da una classe base, "dove tutto è" - tutto funziona, ma fino a quando non vogliamo provare a fare diversi campi di classe, e poi vogliamo aggiungere più campi in ogni classe di campo, e inchiodare il tutto con un array dinamico di classi

e poi otterremo che non possiamo implementare il metodo Save(int hndl) stesso in una classe base - questo metodo sarà in realtà un'interfaccia, che, come discusso sopra, non sarà affatto necessaria - si può scrivere senza interfacce

Di solito massimizzo i miei sforzi sulla flessibilità del codice - minimo di confusione - il risultato è un nuovo problema risolto, che la mia terminologia sia perdonata)))


il problema sarà, quando si implementa il salvataggio su file, è necessarioelaborare l'intestazione del file, che dovrebbe descrivere la quantità totale di diversi tipi di voci e poi è necessario non perdere la logica / ordine di salvataggio dei dati, al fine di leggere tutto correttamente.... e il finale sarà se si cambia anche un solo campo in una classe

imho, la laboriosità di tale eredità "facile" da una classe base - si riduce allo sviluppo e alla manutenzione di un piccolo database, al monitoraggio costante dei cambiamenti in qualsiasi classe

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

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

Qualcosa come questo))))

 
Vladimir Simakov:

Qualcosa come questo))))

Capisco tutto questo, ma al vecchio detto "MQL non è C", si può solo aggiungere che non ha senso fare affidamento su un codice ben strutturato per compiti - i compiti MQL sono sempre altamente specializzati e il riutilizzo di grande codice spesso non è efficace.

HH: imho l'obiettivo principale del codice MQL è quello di essere il più veloce possibile, per essere utilizzato nel tester o per eseguire il codice entro un tick - senza perdere tick, è tutto chiaro, ma ci sono alcune restrizioni - non si possono ignorare i guasti di connessione e il riavvio del PC / terminale, ed è tutto su come trovare l'ottimale, non soloun codicebello e strutturato

 
Igor Makanu:

2. c'è un trucco per descrivere operator= , e usare l'operatore di copia nativo in esso? .... cioè un modo per chiamare : :=

c'è un modo, e come al solito la soluzione è semplice:

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

inizializziamo la matrice A, quindi C

assegniamo prima una nuova matrice B = A e disinizializziamo, poi B = C e disinizializziamo

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

il punto - è necessario avvolgere la struttura nella struttura e di nuovo nella struttura.... scusate il mio termine tecnico ))))


SZY: la soluzione è buona, dovremmo sostituire i metodi RowCount() e ColCount() con i campi della struttura RowCount e ColCount(), per fare meno chiamate... Ma nel complesso, funziona come volevo

 
Dici sul serio?
 
Алексей Тарабанов:
Dici sul serio?

Qual è il problema, l'uomo sta risolvendo questo problema dal 2012, non disturbatelo, lo sa meglio di tutti.

 
Sergey Dzyublik:

Qual è il problema, l'uomo sta risolvendo questo problema dal 2012, non disturbatelo, lo sa meglio di tutti.

Stai pensando in modo piatto.

il compito è quello di conoscere le capacità tecniche del linguaggio MQL, in modo che un tale esempiohttps://docs.microsoft.com/en-us/archive/msdn-magazine/2018/april/test-run-understanding-lstm-cells-using-csharp

può essere portato "direttamente" - questo compito è stato risolto ora, portando tutte le funzioni dell'esempio uno a uno con una sola assunzione: float[][] result --> SMatrix result

 
Igor Makanu:

c'è un modo, e come al solito la soluzione è semplice:

inizializzare la matrice A, quindi C

prima assegna una nuova matrice B = A e disinizializza, poi B = C e disinizializza


HH: la soluzione è buona, dobbiamo sostituire i metodi RowCount() e ColCount() con i campi della struttura RowCount e ColCount() per fare meno chiamate ... Ma nel complesso, tutto funziona come volevo.

Sfortunatamente, non tutto è felice come avremmo voluto. In MQL, c'è un bug di lunga data con la copia di array da parte dell'operatore di copia predefinito. Solo ArrayCopy di elementi da un array in un altro ha luogo. La dimensione dell'array risultante non è sincronizzata con l'origine (non è troncata). Ciò significa che se sono stati usati A(10) e B(20), dopo B=A si otterrà anche B(20), cioè metà degli elementi saranno sostituiti con elementi di A, il resto rimarrà lo stesso. Questo, naturalmente, non è affatto quello che ci si aspetta dall'operatore=. Ecco perché dovremo scrivere il nostro operatore per gli array.

Devo ammettere che pensavo che questo bug fosse già stato risolto. Ma ho controllato ed è ancora lì.

 
Alexey Navoykov:

Sfortunatamente, non tutto è felice come vorremmo. MQL ha un bug di lunga data con la copia di array tramite l'operatore di copia predefinito. Si verifica solo ArrayCopy di elementi da un array all'altro. La dimensione dell'array risultante non è sincronizzata con l'origine (non è troncata). Significa che se A(10) e B(20) erano presenti, dopo B=A si otterrà anche B(20), cioè metà degli elementi saranno sostituiti con elementi da A, il resto rimarrà lo stesso. Questo, naturalmente, non è affatto quello che ci si aspetta dall'operatore=. Ecco perché dovremo scrivere il nostro operatore per gli array.

Devo confessare che pensavo che questo bug fosse già stato risolto. Ma ho controllato ed è ancora lì.

L'insetto è stato recentemente richiamato:

Forum sul trading, sistemi di trading automatico e test di strategia

Domande OOP in MQL5

Sergey Dzyublik, 2020.04.18 17:48

Allora, secondo la vostra terminologia, chiamare l'operatore di assegnazione predefinito può dare un "tipo di dati incompleto".
Bug del 2019.05.03 mai risolto:https://www.mql5.com/ru/forum/1111/page2451#comment_11556395


La linea data dovrebbe bypassare il bug:

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 linea data dovrebbe bypassare il bug:

Oh, sì, non l'ho notato all'inizio... Ma allora avresti potuto scrivere subito ArrayCopy. Perché abbiamo bisogno di questa guarnizione SMATRIX allora?

 
Alexey Navoykov:

Oh, sì, non l'ho notato all'inizio... Ma allora avresti potuto scrivere subito ArrayCopy. Perché abbiamo bisogno di questo blocco SMATRIX?...

Gli sviluppatori МТТ scrivono sempre che l'uso dei meccanismi incorporati del compilatore sarà più veloce anche di chiamare le funzioni standard

Se avete tempo e interesse, controllate la velocità della mia versione e della vostra con ArrayCopy

Controllerò la velocità un po' più tardi, sono nel mezzo di una lezione