Fragen zu OOP in MQL5 - Seite 46

 
Igor Makanu:

Das ist genau das, wovon ich weggekommen bin, und genau das habe ich anfangs auch getan.

mit diesem Ansatz - von einer Basisklasse zu erben, "wo alles ist" - funktioniert alles, aber bis wir versuchen wollen, mehrere Klassenfelder zu machen, und dann wollen wir mehr Felder in jeder Feld-Klasse hinzufügen, und nageln Sie alles mit einem dynamischen Array von Klassen

und dann werden wir feststellen, dass wir die Methode Save(int hndl) selbst nicht in einer Basisklasse implementieren können - diese Methode wird eigentlich eine Schnittstelle sein, die, wie oben besprochen, überhaupt nicht benötigt wird - man kann sie ohne Schnittstellen schreiben

Normalerweise maximiere ich meine Bemühungen auf die Flexibilität des Codes - minimaler Aufwand - das Ergebnis ist ein neues gelöstes Problem, man möge mir meine Terminologie verzeihen)))


Das Problem besteht darin, dass Sie bei der Implementierung des Speicherns in eine Dateiden Dateikopf aus arbeiten müssen, der die Gesamtmenge der verschiedenen Arten von Einträgen beschreiben sollte, und dann müssen Sie die Logik/Reihenfolge der Datenspeicherung nicht verlieren, um alles korrekt zu lesen.... und das Finale wird sein, wenn Sie auch nur ein Feld in einer Klasse ändern

imho ist die "einfache" Vererbung von einer Basisklasse sehr mühsam - sie erfordert die Entwicklung und Pflege einer kleinen Datenbank und die ständige Überwachung von Änderungen in jeder Klasse

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

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

Etwa so: ))))

 
Vladimir Simakov:

Etwa so: ))))

Ich verstehe das alles, aber zu dem alten Spruch "MQL ist nicht C" kann man nur hinzufügen, dass es keinen Sinn macht, sich auf einen gut strukturierten Code nach Aufgaben zu verlassen - MQL-Aufgaben sind immer hochspezialisiert und die Wiederverwendung von großem Code ist oft nicht effektiv.

HH: imho ist das Hauptziel des MQL-Codes, so schnell wie möglich zu sein, um im Tester verwendet zu werden oder den Code innerhalb eines Ticks auszuführen - ohne Ticks zu verlieren, es ist alles klar, aber es gibt einige Einschränkungen - man kann die Situation mit Verbindungsabbrüchen und PC / Terminal-Neustart nicht ignorieren, und es geht darum, das Optimum zu finden, nicht nureinen schönen und strukturierten Code

 
Igor Makanu:

2. Gibt es einen Hack, um operator= zu beschreiben und den nativen Kopieroperator darin zu verwenden? .... d.h. eine Möglichkeit zum Aufruf von : :=

es gibt einen Weg, und wie immer ist die Lösung einfach:

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

wir initialisieren die Matrix A, dann C

wird zunächst eine neue Matrix B = A zugewiesen und die Initialisierung aufgehoben, dann B = C und die Initialisierung aufgehoben

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

der Punkt - Sie müssen die Struktur in die Struktur und wieder in die Struktur einpacken.... entschuldigen Sie meinen Fachausdruck ))))


SZY: Die Lösung ist gut, wir sollten die Methoden RowCount() und ColCount() durch Strukturfelder RowCount und ColCount() ersetzen, um weniger Aufrufe zu machen... Aber im Großen und Ganzen funktioniert es so, wie ich es haben wollte.

 
Ist das Ihr Ernst?
 
Алексей Тарабанов:
Ist das Ihr Ernst?

Was ist schon dabei, der Mann hat dieses Problem seit 2012 gelöst, stören Sie ihn nicht, er weiß es am besten.

 
Sergey Dzyublik:

Was ist schon dabei, der Mann hat dieses Problem seit 2012 gelöst, belästigen Sie ihn nicht, er weiß es am besten.

Sie denken flach.

die Aufgabe ist es, die technischen Möglichkeiten der MQL-Sprache zu kennen, so dass ein solches Beispielhttps://docs.microsoft.com/en-us/archive/msdn-magazine/2018/april/test-run-understanding-lstm-cells-using-csharp

kann "direkt" portiert werden - diese Aufgabe wurde nun gelöst, indem alle Funktionen des Beispiels eins-zu-eins mit einer Annahme portiert wurden: float[][] result --> SMatrix result

 
Igor Makanu:

es gibt einen Weg, und wie immer ist die Lösung einfach:

die Matrix A initialisieren, dann C

zuerst eine neue Matrix B = A zuweisen und entinitialisieren, dann B = C und entinitialisieren


HH: Die Lösung ist gut, wir müssen die Methoden RowCount() und ColCount() durch Strukturfelder RowCount und ColCount() ersetzen, um weniger Aufrufe zu machen ... Aber im Großen und Ganzen funktioniert alles so, wie ich es wollte.

Leider ist nicht alles so glücklich, wie wir es uns gewünscht hätten. In MQL gibt es einen langjährigen Fehler beim Kopieren von Arrays durch den Standard-Kopieroperator. Es ist nur ArrayCopy von Elementen von einem Array in ein anderes, das auftritt. Die Größe des resultierenden Arrays ist nicht mit der Quelle synchronisiert (es wird nicht abgeschnitten), d.h. wenn A(10) und B(20) verwendet wurden, erhält man nach B=A auch B(20), d.h. die Hälfte der Elemente wird durch Elemente aus A ersetzt, der Rest bleibt gleich. Das ist natürlich ganz und gar nicht das, was man von dem Operator= erwartet. Deshalb müssen wir einen eigenen Operator für Arrays schreiben.

Ich muss gestehen, dass ich dachte, dieser Fehler sei bereits behoben worden. Aber ich habe es überprüft und es ist immer noch da.

 
Alexey Navoykov:

Leider ist nicht alles so glücklich, wie wir es gerne hätten. MQL hat einen langjährigen Fehler beim Kopieren von Arrays mit dem Standard-Kopieroperator. Nur ArrayCopy von Elementen von einem Array in ein anderes tritt auf. Die Größe des resultierenden Arrays ist nicht mit der Quelle synchronisiert (es wird nicht abgeschnitten), d.h. wenn A(10) und B(20) verwendet wurden, erhält man nach B=A auch B(20), d.h. die Hälfte der Elemente wird durch Elemente aus A ersetzt, der Rest bleibt gleich. Das ist natürlich ganz und gar nicht das, was man von dem Operator= erwartet. Deshalb müssen wir einen eigenen Operator für Arrays schreiben.

Ich muss gestehen, dass ich dachte, dieser Fehler sei bereits behoben worden. Aber ich habe es überprüft und es ist immer noch da.

Der Käfer wurde kürzlich zurückgerufen:

Forum für Handel, automatisierte Handelssysteme und Strategietests

OOP-Fragen in MQL5

Sergey Dzyublik, 2020.04.18 17:48

Dann kann der Aufruf des Standard-Zuweisungsoperators Ihrer Terminologie zufolge einen "unvollständigen Datentyp" ergeben.
Fehler aus 2019.05.03 nie behoben:https://www.mql5.com/ru/forum/1111/page2451#comment_11556395


Mit der angegebenen Zeile soll der Fehler umgangen werden:

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:

Die angegebene Zeile sollte den Fehler umgehen:

Oh ja, das ist mir zuerst gar nicht aufgefallen... Aber dann hätte man ja gleich ArrayCopy schreiben können. Wozu brauchen wir dann überhaupt diese SMATRIX-Dichtung...

 
Alexey Navoykov:

Oh ja, das ist mir zuerst gar nicht aufgefallen... Aber dann hätten Sie ja gleich ArrayCopy schreiben können. Wozu brauchen wir überhaupt dieses SMATRIX-Pad?...

МТ Entwickler schreiben immer, dass die Verwendung eingebauter Compiler-Mechanismen sogar schneller ist als der Aufruf von Standardfunktionen

Wenn Sie Zeit und Interesse haben, überprüfen Sie die Geschwindigkeit meiner und Ihrer Version mit ArrayCopy

Ich werde die Geschwindigkeit später überprüfen, ich bin mitten in einer Unterrichtsstunde.

Grund der Beschwerde: