Domande su OOP in MQL5 - pagina 16

 
Dmitry Fedoseev:

Lalibreria standard presuppone che i controlli siano creati su un modulo. Non dovrebbero funzionare affatto, proprio così. Almeno, così era una volta.

Dovrò provare le ultime versioni della serie GUI di Kajarski. Quanto velocemente funziona per lui. E poi scrivere di nuovo agli sviluppatori per mettere a punto la loro invenzione.
 
Vasiliy Pushkaryov:
Dovrò provare l'ultima versione della serie di articoli di Kajarsky sulla GUI. Quanto velocemente funziona per lui. E poi ancora una volta scrivere agli sviluppatori per mettere a punto la loro invenzione.

tutti camminano nello stesso cerchio! ))) - È da questa serie di articoli sulle interfacce grafiche che ho iniziato a studiare le capacità MQL .... - L'esperienza non è stata buona, alcuni degli esempi negli articoli non si compilano più, l'autore si tiene in contatto, ma la dimensione della libreria è molto grande, non ho iniziato ad usarla, anche se potreste riuscirci.

imho - o studiate C# per una settimana - avete un sacco di esempi sul web e il form designer in VS è lo stesso di Delphi (ho scritto prima in Delphi), o usate comunque SB - almeno ha il supporto degli sviluppatori

 
Igor Makanu:

tutti camminano nello stesso cerchio! ))) - È da questa serie di articoli sulle interfacce grafiche che ho iniziato a studiare le capacità MQL .... - L'esperienza non è stata buona, alcuni degli esempi negli articoli non si compilano più, l'autore si tiene in contatto, ma la dimensione della libreria è molto grande, non ho iniziato ad usarla, anche se potreste riuscirci.

imho, o impara C# per una settimana - hai un sacco di esempi sul web e il form designer in VS è lo stesso di Delphi (in Delphi ho scritto prima), o usa SB lo stesso - almeno ha il supporto degli sviluppatori

Mi dispiace sentire che la biblioteca è già stata impacchettata. L'ho provato circa un anno fa, mi piaceva l'aspetto del pannello. L'ho anche modificato per MT4 e l'ho provato (a causa delle differenze in Canvas non ha compilato subito), ma poi, a causa della difficoltà di portarlo per il mio compito, ho preso SB. Ho pensato di tornare alle GUI più tardi.

Non credo di poter padroneggiare C# in una settimana. Ma devo pormi un obiettivo, inoltre c'è già il supporto nativo per le librerie .NET. Qui hai suggerito come può essere usato per il tuo particolare compito.

 
Vladimir Simakov:

E nel secondo caso è necessario

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

Non ha funzionato con la tua versione per qualche motivo, forse ho fatto di nuovo casino )) ,

Voglio salvare i dati in una lista senza puntatori intermedi, funziona così e senza perdite di memoria:

#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;
  }
//+------------------------------------------------------------------+

questo è solo l'inizio della mia idea

Voglio implementare nel mio template la scrittura e la lettura in un file binario (anche se potrei farlo in un file di testo, non importa). Non ho idea di come scrivere CData in un file usando un template di classe field - ma voglio davvero farlo!

 
Igor Makanu:

Voglio implementare nel mio template la scrittura e la lettura su file binario (anche se è possibile scrivere su file di testo - non è importante), non so come scrivere campi CData su file usando il template - ma lo voglio davvero!)

#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);
  }
//+------------------------------------------------------------------+

Non ho mai lavorato con CList e CObject, ma i sorgenti sono semplici (a proposito, c'è un metodo virtuale Save senza modificatore const per qualche motivo), quindi ha funzionato subito.


SZY È più facile scrivere così.

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

Allora non avrete bisogno di costruttore/distruttore. Ha senso usare new/delete dove è veramente utile. Altrimenti potete fare lo stesso come con FILE sopra.

 
fxsaber:

Non ho mai lavorato con CList e CObject, ma il codice sorgente è semplice, quindi ha funzionato subito.

Oh, hai avuto la tua risposta così in fretta! - GRAZIE! - Avrò qualcosa da fare la sera.

Ho anche fonte CList e CObject, leggere, non vedere i problemi, ma i test devono condurre

SZZ: qui in generale quello che voglio ottenere... Beh, una specie di lista universale:

1. in cui le strutture di classe possono essere aggiunte immediatamente alla creazione (implementato - controllato il mio esempio data.AddValue(new CData(i,i*2.0)) - OK)

2. in cui si può scrivere e leggere dal file "DB" (iniziato a scrivere, finora il costruttore del modello è

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

funzionano senza scrivere/leggere sul file #1 e #2 leggono il database quando il CDataBase viene creato dal disco e scrivono sul disco quando viene chiamato il distruttore

....

ZS:

qual è lo scopo di tutto questo? -Io scrivo solo EAs secondo uno schema standard - un mago e tutte le manipolazioni con gli ordini attraverso la ricerca di un ordine con un mago, se il TS non è "101 indicatore" ma più complicato, di solito 2 maghi sono sufficienti, ma se il TS sta monitorando 80 ordini pendenti (10 griglie di ordini, le griglie vengono riaperte e ... Ad essere onesti è assurdo ma l'ho incontrato per la seconda volta), poi comincio ad usare vari trucchi - condurre 80 ordini su 80 maghi generati ))) - Ne sono uscito, ma non mi piace tutto

Vorrei finalmente creare un piccolo database dove sarei in grado di scrivere dati sugli ordini (tutto il resto) e, soprattutto, non prestare attenzione al database stesso - accesso come aglielementi dell'array, leggere e scrivere su un file quando l'EA viene aperto o chiuso

e così via ))))


fxsaber:

SZZ È più facile scrivere

Allora non avete bisogno di un costruttore/distruttore. Il nuovo/cancellato dovrebbe essere usato dove è veramente utile. Per il resto, potete fare quello che avete fatto con FILE sopra.

Grazie, ma devo ancora pensarci... o meglio voglio farlo in modo da non doverci pensare dopo))) - quando OnInit() crea il database, legge il file e DeInit() uccide il database, salva il file e se hai mancato la cancellazione in DeInit(), il terminale scriverà qualcosa nel diario... Secondo me esclude gli errori quando si lavora con il database... in generale, se lo faccio, vedrò quanto è conveniente

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

se non ti dispiace, perché usare " :: "https://www.mql5.com/ru/docs/basis/operations/other

 
Igor Makanu:

se non ti dispiace, perché usiamo " :: " qui?

Altrimenti devo controllare che le classi madri non abbiano un metodo con lo stesso nome. E anche se non c'è, se qualcuno lo aggiunge, il codice funzionerà comunque.

Per la stessa ragione uso sempre questo per l'univocità e la leggibilità.


ZZY Ma in alcune rare situazioni :: e questo toglie flessibilità. Ci sono sottigliezze simili su quando è meglio scrivere il corpo del metodo dentro la classe e quando fuori. Ricordo di aver incontrato tutto questo, ma non farò esempi.

 
fxsaber:

Altrimenti devo controllare che le classi madri non abbiano un metodo con lo stesso nome. E anche se non c'è, se qualcuno lo aggiunge, il codice funzionerà comunque.

Per la stessa ragione uso sempre questo per chiarezza e leggibilità.

Sì, è davvero pratico e previene i bug, lo terrò in considerazione

Grazie!

 
Igor Makanu:

4. se il flag di scrittura del file m_fsave è attivo, allora ogni volta che chiamiamo il metodo AddValue() - aggiungiamo più dati al file

Guarda il formato del record CList. Lo state ignorando.

Motivazione: