Questions sur la POO dans MQL5 - page 16

 
Dmitry Fedoseev:

Labibliothèque standard suppose que les contrôles sont créés sur un formulaire. Ils ne sont pas censés fonctionner du tout, juste comme ça. Du moins, c'est comme ça que ça se passait.

Je vais devoir essayer les dernières versions de la série GUI de Kajarski. La rapidité avec laquelle ça marche pour lui. Et puis écrire à nouveau aux développeurs pour qu'ils peaufinent leur invention.
 
Vasiliy Pushkaryov:
Je vais devoir essayer la dernière version de la série d'articles de Kajarsky sur les interfaces graphiques. La rapidité avec laquelle ça marche pour lui. Et puis, une fois de plus, écrire aux développeurs pour qu'ils peaufinent leur idée.

tout le monde marche dans le même cercle ! ))) - C'est à partir de cette série d'articles sur les interfaces graphiques que j'ai commencé à étudier les capacités de MQL ..... - L'expérience n'a pas été bonne, certains des exemples dans les articles ne compilent plus, l'auteur garde le contact, mais la taille de la bibliothèque est très grande, je n'ai pas commencé à l'utiliser, bien que vous puissiez y réussir.

imho - soit vous étudiez le C# pendant une semaine - vous avez beaucoup d'exemples sur le web et le concepteur de formulaire dans VS est le même que dans Delphi (j'ai écrit plus tôt en Delphi), soit vous utilisez SB de toute façon - au moins il a le soutien des développeurs.

 
Igor Makanu:

tout le monde marche dans le même cercle ! ))) - C'est à partir de cette série d'articles sur les interfaces graphiques que j'ai commencé à étudier les capacités de MQL ..... - L'expérience n'a pas été bonne, certains des exemples dans les articles ne compilent plus, l'auteur garde le contact, mais la taille de la bibliothèque est très grande, je n'ai pas commencé à l'utiliser, bien que vous puissiez y réussir.

imho, ou apprendre C# pendant une semaine - vous avez beaucoup d'exemples sur le web et le concepteur de formulaire dans VS est le même que dans Delphi (dans Delphi j'ai écrit plus tôt), ou utiliser SB tout de même - au moins il a le soutien des développeurs

Désolé d'apprendre que la bibliothèque est déjà emballée. Je l'ai essayé il y a environ un an, j'ai aimé l'aspect du panneau. Je l'ai même modifié pour MT4 et l'ai essayé (à cause des différences dans Canvas, il n'a pas été compilé tout de suite non plus). Mais ensuite, en raison de la difficulté de le porter pour ma tâche, j'ai pris SB. J'ai pensé revenir aux interfaces graphiques plus tard.

Je ne pense pas que je pourrais maîtriser le C# en une semaine. Mais je dois me fixer un objectif. De plus, il existe déjà un support natif pour les bibliothèques .NET. Ici, vous avez suggéré comment il peut être utilisé pour votre tâche particulière.

 
Vladimir Simakov:

Et dans le second cas, vous devez

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

Cela n'a pas fonctionné avec votre version pour une raison quelconque, peut-être que j'ai encore fait une erreur ;)) ,

Je veux enregistrer des données dans une liste sans pointeurs intermédiaires, cela fonctionne de cette façon et sans fuites de mémoire :

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

ce n'est que le début de mon idée

Je veux implémenter dans mon modèle l'écriture et la lecture dans un fichier binaire (bien que je puisse le faire dans un fichier texte, cela n'a pas d'importance). Je n'ai aucune idée de la façon d'écrire des données dans un fichier en utilisant un modèle de classe champ - mais je veux vraiment le faire !

 
Igor Makanu:

Je veux implémenter dans mon modèle l'écriture et la lecture dans un fichier binaire (bien qu'il soit possible d'écrire dans un fichier texte - ce n'est pas important), je ne sais pas comment écrire des champs de CData dans un fichier en utilisant le modèle - mais je le veux vraiment ! ;)

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

Je n'ai jamais travaillé avec CList et CObject, mais les sources sont simples (au fait, il y a une méthode virtuelle Save sans modificateur const pour une raison quelconque), donc ça a marché tout de suite.


SZY C'est plus facile de l'écrire.

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

Alors vous n'aurez pas besoin de constructeur/destructeur. Il est logique d'utiliser new/delete là où c'est vraiment utile. Sinon, vous pouvez faire la même chose qu'avec FILE ci-dessus.

 
fxsaber:

Je n'ai jamais travaillé avec CList et CObject, mais le code source est simple, donc ça a marché tout de suite.

Oh ! tu as eu ta réponse si rapidement ! - MERCI ! - J'aurai quelque chose à faire le soir.

Je source également CList et CObject, lire, ne voient pas les problèmes, mais les tests doivent effectuer

SZZ : voici en général ce que je veux obtenir... Eh bien, une sorte de liste universelle :

1. dans lequel les structures de classe peuvent être ajoutées immédiatement à la création (implémenté - vérifié mon exemple data.AddValue(new CData(i,i*2.0)) - OK)

2. dans lequel vous pouvez écrire et lire le fichier "DB" (commencé à écrire, jusqu'à présent le constructeur de modèle est

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

fonctionnent sans écriture/lecture dans le fichier #1 et #2 lisent la base de données lorsque la CDataBase est créée à partir du disque et écrivent sur le disque lorsque le destructeur est appelé.

....

ZS :

Quel est l'intérêt de tout ça ? -Je me contente d'écrire des EAs selon un schéma standard - un magicien et toutes les manipulations avec les ordres par la recherche d'un ordre avec un magicien, si le TS n'est pas "101 indicateur" mais plus compliqué, généralement 2 magiciens suffisent, mais si le TS surveille 80 ordres en attente (10 grilles d'ordres, les grilles sont rouvertes et .... Pour être honnête, c'est absurde mais je l'ai rencontré pour la deuxième fois), puis je commence à utiliser divers trucs - mener 80 commandes sur 80 magiciens générés ;))). - Je m'en suis sorti, mais je n'aime pas tout ça.

Je voudrais enfin créer une petite base de données où je pourrais écrire des données sur les ordres (tout le reste) et, surtout, ne pas faire attention à la base de données elle-même - accès comme auxéléments du tableau, lecture et écriture dans un fichier lorsque l'EA est ouvert ou fermé

et ainsi de suite ))))


fxsaber:

SZZ C'est plus facile d'écrire

Alors vous n'avez pas besoin d'un constructeur/destructeur. La fonction "nouveau/supprimé" doit être utilisée lorsqu'elle est vraiment utile. Pour le reste, vous pouvez faire ce que vous avez fait avec FILE ci-dessus.

Merci, mais je dois encore y réfléchir ... ou plutôt je veux le faire de telle sorte que je n'aie pas à y réfléchir plus tard))). - quand OnInit() crée la base de données, il lit le fichier et DeInit() tue la base de données, il sauvegarde le fichier et si vous avez manqué la suppression dans DeInit(), le terminal écrira quelque chose à ce sujet dans le journal... A mon avis, cela exclut les erreurs lors du travail avec la base de données... en général, si je le fais, je verrai à quel point c'est pratique

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

si cela ne vous dérange pas, pourquoi utiliser " : : "https://www.mql5.com/ru/docs/basis/operations/other

 
Igor Makanu:

Si cela ne vous dérange pas, pourquoi utilise-t-on " : : " ici ?

Sinon, je dois vérifier que les classes parentes n'ont pas de méthode portant le même nom. Et même s'il n'y en a pas, si quelqu'un l'ajoute, le code fonctionnera toujours.

Pour la même raison, je l'utilise toujours pour l'absence d'ambiguïté et la lisibilité.


ZZY Mais dans certaines situations rares : : et cela enlève de la flexibilité. Il existe des subtilités similaires quant à savoir quand il est préférable d'écrire le corps de la méthode à l'intérieur de la classe et quand il est préférable de l'écrire à l'extérieur. Je me souviens avoir rencontré tout cela, mais je ne donnerai pas d'exemples.

 
fxsaber:

Sinon, je dois vérifier que les classes parentes n'ont pas de méthode portant le même nom. Et même s'il n'y en a pas, si quelqu'un l'ajoute, le code fonctionnera toujours.

Pour la même raison, je l'utilise toujours pour l'absence d'ambiguïté et la lisibilité.

Oui, c'est vraiment pratique et cela évite les bugs, je vais en tenir compte.

Merci !

 
Igor Makanu:

4. si l'indicateur d'écriture de fichier m_fsave est actif, chaque fois que nous appelons la méthode AddValue(), nous ajoutons des données au fichier.

Regardez le format d'enregistrement de CList. Vous l'ignorez.

Raison: