Fragen zu OOP in MQL5 - Seite 16

 
Dmitry Fedoseev:

DieStandardbibliothek geht davon aus, dass Steuerelemente auf einem Formular erstellt werden. Sie sollen überhaupt nicht funktionieren, einfach so. Zumindest war das früher so.

Ich werde die neuesten Versionen von Kajarskis GUI-Serie ausprobieren müssen. Wie schnell es bei ihm funktioniert. Und dann schreiben Sie erneut an die Entwickler, um ihre Idee zu verbessern.
 
Vasiliy Pushkaryov:
Ich werde die neueste Version von Kajarskys Artikelserie über GUI ausprobieren müssen. Wie schnell es bei ihm funktioniert. Und dann schreiben sie wieder an die Entwickler, um ihre Idee zu verbessern.

alle gehen im gleichen Kreis! ))) - Ausgehend von dieser Artikelserie über grafische Schnittstellen begann ich, die MQL-Fähigkeiten zu studieren .... - Die Erfahrung war nicht gut, einige der Beispiele in den Artikeln kompilieren nicht mehr, der Autor bleibt in Kontakt, aber die Größe der Bibliothek ist sehr groß, ich habe nicht begonnen, diese Bibliothek zu verwenden, obwohl Sie es schaffen können.

imho - entweder Sie studieren C# für eine Woche - Sie haben viele Beispiele im Web und der Formular-Designer in VS ist das gleiche wie in Delphi (ich schrieb früher in Delphi), oder verwenden Sie SB sowieso - zumindest hat es Unterstützung von den Entwicklern

 
Igor Makanu:

alle gehen im gleichen Kreis! ))) - Ausgehend von dieser Artikelserie über grafische Schnittstellen begann ich, die MQL-Fähigkeiten zu studieren .... - Die Erfahrung war nicht gut, einige der Beispiele in den Artikeln kompilieren nicht mehr, der Autor bleibt in Kontakt, aber die Größe der Bibliothek ist sehr groß, ich habe nicht begonnen, es zu benutzen, obwohl Sie es schaffen können.

imho, oder lernen Sie C# für eine Woche - Sie haben viele Beispiele im Web und der Formular-Designer in VS ist das gleiche wie in Delphi (in Delphi schrieb ich früher), oder verwenden Sie SB sowieso - zumindest hat es Unterstützung von den Entwicklern

Es tut mir leid zu hören, dass die Bibliothek bereits verpackt ist. Ich habe es vor etwa einem Jahr ausprobiert, und mir gefiel das Aussehen der Platte. Ich habe es sogar für MT4 optimiert und ausprobiert (wegen der Unterschiede in Canvas ließ es sich auch nicht sofort kompilieren), aber dann habe ich wegen der Schwierigkeit, es für meine Aufgabe zu portieren, SB genommen. Ich dachte, ich käme später auf GUIs zurück.

Ich glaube nicht, dass ich C# in einer Woche beherrschen könnte. Aber ich muss mir ein Ziel setzen, außerdem gibt es bereits native Unterstützung für .NET-Bibliotheken. Hier haben Sie vorgeschlagen, wie es für Ihre spezielle Aufgabe verwendet werden kann.

 
Vladimir Simakov:

Und im zweiten Fall müssen Sie

void  AddValue (T &value)  { Tptr  = value; mlist.Add(Tptr);       }

Aus irgendeinem Grund hat es mit deiner Version nicht funktioniert, vielleicht habe ich es wieder verbockt )) ,

Ich möchte Daten in einer Liste ohne Zwischenzeiger speichern, es funktioniert auf diese Weise und ohne Speicherlecks:

#property strict
#include <Arrays\List.mqh>
//+------------------------------------------------------------------+
template<typename T>class CDataBase
  {
private:
   CList            *mlist;
public:
   void CDataBase()           { mlist=new CList;                                    }
   void ~CDataBase(void)      { delete mlist;                                       }
   int ArraySize(void)        { return(mlist.Total());                              }
   T operator[](int index)    { return(mlist.GetNodeAtIndex(index));                }
   void  AddValue (T value)   { mlist.Add(value);                                   }
   void  Delete(int pos)      { mlist.Delete(pos);                                  }
   string TypeName()          { return(typename(T));                                }
  };

//+------------------------------------------------------------------+
class CData : public CObject
  {
public:
   int               x;
   double            y;
                     CData(){};
                     CData(int ival,double dval){x=ival;y=dval;}
  };
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnStart()
  {
   CDataBase<CData*>*data=new CDataBase<CData*>;
   int i;
   for(i=0; i<5; i++) data.AddValue(new CData(i,i*2.0));
   Print("Тип БД : ", data.TypeName()," б чтение данных :");
   for(i=0; i<data.ArraySize(); i++) Print(i," : ",data[i].x," , ",data[i].y);
   Print("Удалил № 3");
   data.Delete(3);
   for(i=0; i<data.ArraySize(); i++) Print(i," : ",data[i].x," , ",data[i].y);
   delete data;
  }
//+------------------------------------------------------------------+

dies ist nur der Anfang meiner Idee

Ich möchte in meiner Vorlage das Schreiben und Lesen in eine Binärdatei implementieren (obwohl ich es auch mit einer Textdatei tun könnte, das spielt keine Rolle). Ich habe keine Ahnung, wie man CD-Daten in eine Datei schreibt, indem man eine Vorlage der Klasse field verwendet - aber ich möchte es wirklich tun!

 
Igor Makanu:

Ich möchte in meiner Vorlage Schreiben und Lesen in eine Binärdatei implementieren (obwohl es möglich ist, in eine Textdatei zu schreiben - nicht wichtig), ich weiß nicht, wie man CData-Felder in eine Datei schreiben kann, indem man eine Vorlage verwendet - aber ich will es wirklich!)

#property strict
#include <Arrays\List.mqh>
//+------------------------------------------------------------------+
struct FILE
{
  const int handle;
  
  FILE( const string FileName, const int Flags ) : handle(::FileOpen(FileName, Flags)) {}  
  ~FILE( void ) { if (this.handle != INVALID_HANDLE) ::FileClose(this.handle); }
};

template <typename T>
class CList2 : public CList
{
public:  
  virtual CObject  *CreateElement(void) { return(new T); }
};

template<typename T>class CDataBase
  {
private:
   CList2<T>            *mlist;
public:
   void CDataBase()           { mlist=new CList2<T>;                                    }
   void ~CDataBase(void)      { delete mlist;                                       }
   int ArraySize(void)        { return(mlist.Total());                              }
   T* operator[](int index)    { return(mlist.GetNodeAtIndex(index));                }
   void  AddValue (T* value)   { mlist.Add(value);                                   }
   void  Delete(int pos)      { mlist.Delete(pos);                                  }
   string TypeName()          { return(typename(T));                                }
  bool Save( const string FileName ) const { const FILE File(FileName, FILE_WRITE | FILE_BIN); return(this.mlist.Save(File.handle)); }
  bool Load( const string FileName ) { const FILE File(FileName, FILE_READ | FILE_BIN); return(this.mlist.Load(File.handle)); }

  };

//+------------------------------------------------------------------+
class CData : public CObject
  {
public:
   int               x;
   double            y;
                     CData(){};
                     CData(int ival,double dval){x=ival;y=dval;}
   virtual bool      Save( const int file_handle ) { return(::FileWriteInteger(file_handle, this.x) && ::FileWriteDouble(file_handle, this.y)); }
   virtual bool      Load( const int file_handle )
   {
     ::ResetLastError();
     
     this.x = ::FileReadInteger(file_handle);
     this.y = ::FileReadDouble(file_handle);
     
     return(!::GetLastError());
   }
  };
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnStart()
  {
   CDataBase<CData>*data=new CDataBase<CData>;
   int i;
   for(i=0; i<5; i++) data.AddValue(new CData(i,i*2.0));
   Print("Тип БД : ", data.TypeName()," б чтение данных :");
   for(i=0; i<data.ArraySize(); i++) Print(i," : ",data[i].x," , ",data[i].y);
   
   data.Save("Data.bin");
   delete data;

   CDataBase<CData> data2;   
   data2.Load("Data.bin");
   Print("Тип БД : ", data2.TypeName()," б чтение данных :");
   for(i=0; i<data2.ArraySize(); i++) Print(i," : ",data2[i].x," , ",data2[i].y);
  }
//+------------------------------------------------------------------+

Ich habe nie mit CList und CObject gearbeitet, aber die Quellen sind einfach (übrigens gibt es eine virtuelle Methode Save ohne Modifikator const aus irgendeinem Grund), so dass es sofort funktionierte.


SZY Es ist einfacher, so zu schreiben.

template<typename T>class CDataBase
  {
private:
   CList2<T>            mlist; // Объект, не указатель

Dann brauchen Sie keinen Konstruktor/Destruktor. Es ist sinnvoll, die Funktion "Neu/Löschen" dort zu verwenden, wo sie wirklich nützlich ist. Andernfalls können Sie genauso verfahren wie bei FILE oben.

 
fxsaber:

Ich habe noch nie mit CList und CObject gearbeitet, aber der Quellcode ist so einfach, dass es auf Anhieb funktioniert.

Oh! Sie haben so schnell eine Antwort bekommen! - DANKESCHÖN! - Ich werde nachts etwas zu tun haben.

Ich auch Quelle CList und CObject, lesen, nicht sehen, die Probleme, aber Tests durchführen müssen

SZZ: Hier im Allgemeinen, was ich erreichen möchte... eine Art universelle Liste:

1. in denen Klassenstrukturen sofort bei der Erstellung hinzugefügt werden können (implementiert - habe mein Beispiel überprüft data.AddValue(new CData(i,i*2.0)) - OK)

2. in der Sie in die "DB"-Datei schreiben und aus ihr lesen können (mit dem Schreiben wurde begonnen, bisher ist der Template-Konstruktor

1. void CDataBase()           { mlist=new CList; m_file_handle=INVALID_HANDLE;         }
2. void CDataBase(int BaseID) { mlist=new CList;m_id=BaseID;m_file_handle=fileopen();  }

ohne Schreiben/Lesen in die Datei funktionieren #1 und #2 die Datenbank lesen, wenn die CDataBase von der Festplatte erstellt wird, und in die Festplatte schreiben, wenn der Destruktor aufgerufen wird

....

ZS:

Was ist der Sinn von all dem? -Ich schreibe nur EAs nach einem Standard-Schema - ein Zauberer und alle Manipulationen mit Aufträgen durch die Suche nach einem Auftrag mit einem Zauberer, wenn die TS ist nicht "101 Indikator", sondern komplizierter, in der Regel 2 Zauberer sind genug, aber wenn die TS ist die Überwachung 80 schwebende Aufträge (10 Grids von Aufträgen, die Raster sind wieder geöffnet und ... Um ehrlich zu sein, es ist absurd, aber ich habe es zum zweiten Mal begegnet), dann beginne ich mit verschiedenen Tricks - führende 80 Aufträge auf 80 generiert Magier ))) - Ich bin da rausgekommen, aber ich mag das alles nicht.

Ich möchte schließlich eine kleine Datenbank erstellen, wo ich in der Lage wäre, Daten über Aufträge (alles andere) zu schreiben und vor allem nicht auf die Datenbank selbst zu achten - Zugriff aufArray-Elemente, Lesen und Schreiben in eine Datei, wenn der EA geöffnet oder geschlossen wird

und so weiter und so fort ))))


fxsaber:

SZZ Es ist einfacher zu schreiben

Dann brauchen Sie keinen Konstruktor/Destruktor. Die Funktion "Neu/Löschen" sollte nur dort verwendet werden, wo sie wirklich nützlich ist. Für den Rest können Sie das tun, was Sie oben mit FILE gemacht haben.

Danke, aber ich muss noch darüber nachdenken ... oder besser gesagt, ich möchte es so machen, dass ich später nicht darüber nachdenken muss))) - wenn OnInit() die Datenbank erstellt, wird die Datei gelesen und DeInit() beendet die Datenbank, speichert die Datei und wenn Sie das Löschen in DeInit() verpasst haben, schreibt das Terminal etwas darüber in das Journal... Meiner Meinung nach schließt es Fehler bei der Arbeit mit der Datenbank aus... Wenn ich es tue, werde ich im Allgemeinen sehen, wie praktisch es ist.

 
fxsaber:
virtual bool      Load( const int file_handle )
   {
     ::ResetLastError();
     

Wenn es Ihnen nichts ausmacht, warum verwenden Sie " :: "https://www.mql5.com/ru/docs/basis/operations/other

 
Igor Makanu:

Wenn es Ihnen nichts ausmacht, warum verwenden wir hier " :: "?

Andernfalls muss ich prüfen, ob die übergeordneten Klassen nicht eine Methode mit demselben Namen haben. Und selbst wenn das nicht der Fall ist, wird der Code funktionieren, wenn jemand ihn hinzufügt.

Aus demselben Grund verwende ich dies immer, um die Eindeutigkeit und Lesbarkeit zu gewährleisten.


ZZY Aber in einigen seltenen Situationen :: und das nimmt die Flexibilität. Es gibt ähnliche Feinheiten darüber, wann es besser ist, den Methodenkörper innerhalb der Klasse zu schreiben und wann es besser ist, ihn außerhalb zu schreiben. Ich erinnere mich, dass ich all dies erlebt habe, aber ich werde keine Beispiele nennen.

 
fxsaber:

Andernfalls muss ich prüfen, ob die übergeordneten Klassen nicht eine Methode mit demselben Namen haben. Und selbst wenn das nicht der Fall ist, wird der Code funktionieren, wenn jemand ihn hinzufügt.

Aus demselben Grund verwende ich dies auch immer, um die Übersichtlichkeit und Lesbarkeit zu gewährleisten.

Ja, das ist wirklich praktisch und verhindert Bugs, ich werde es in Betracht ziehen.

Ich danke Ihnen!

 
Igor Makanu:

4. wenn dasDateischreibkennzeichen m_fsave aktiv ist, werden bei jedem Aufruf der Methode AddValue() weitere Daten zur Datei hinzugefügt

Sehen Sie sich das CList-Datensatzformat an. Sie ignorieren es.

Grund der Beschwerde: