Questions on OOP in MQL5 - page 16

 
Dmitry Fedoseev:

Thestandard library assumes that controls are created on a form. They are not supposed to work at all, just like that. At least, that's how it used to be.

I'll have to try the latest versions of Kajarski's GUI series. How fast it works for him. And then write again to the developers to tweak their brainchild.
 
Vasiliy Pushkaryov:
I will have to try the latest version of Kajarsky's article series on GUI. How fast it works for him. And then once again write to developers to tweak their brainchild.

everyone walks in the same circle! ))) - It was from this series of articles about graphical interfaces that I started to study the MQL capabilities .... - The experience was not good, some of the examples in the articles do not compile anymore, the author keeps in touch, but the size of the library is very large, I have not started to use this library, although you may succeed in it.

imho - you either study C# for a week - you have plenty of examples on the web and the form designer in VS is the same as in Delphi (I wrote earlier in Delphi), or use SB anyway - at least it has support from the developers

 
Igor Makanu:

everyone walks in the same circle! ))) - It was from this series of articles about graphical interfaces that I started to study the MQL capabilities .... - The experience was not good, some of the examples in the articles do not compile anymore, the author keeps in touch, but the size of the library is very large, I have not started to use this library, although you may succeed in it.

imho, or learn C# for a week - you have plenty of examples on the web and the form designer in VS is the same as in Delphi (in Delphi I wrote earlier), or use SB all the same - at least it has support from the developers

Sorry to hear that library is already being wrapped. I tried it a year or so ago, I liked the look of the panel. I even tweaked it for MT4 and tried it (because of the differences in Canvas it didn't compile right away either), but then, due to difficulty of porting it for my task, I took SB. Thought I'd come back to GUIs later.

I don't think I could master C# in a week. But I must set myself a goal, moreover there is already native support for .NET libraries. Here you have suggested how it can be used for your particular task.

 
Vladimir Simakov:

And in the second case you need to

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

It didn't work with your version for some reason, maybe I messed up again )) ,

I want to save data to a list without intermediate pointers, it works this way and without memory leaks:

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

this is just the beginning of my idea

I want to implement into my template writing and reading into binary file (although I could do it into a text file, it doesn't matter). I have no idea how to write CData into a file using a template of class field - but I really want to do it!

 
Igor Makanu:

I want to implement in my template writing and reading to binary file (although it is possible to write to text file - not important), I don't know how to write CData fields to file using template - but I really want to! ;)

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

I've never worked with CList and CObject, but the sources are simple (by the way, there's a virtual method Save without modifier const for some reason), so it worked out at once.


SZY It's easier to write so.

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

Then you won't need constructor/destructor. It makes sense to use new/delete where it's really useful. Otherwise you can do the same as with FILE above.

 
fxsaber:

Never worked with CList and CObject, but the source code is simple, so it worked right away.

Oh! you got an answer so fast! - THANK YOU! - I'll have something to do at night.

I also source CList and CObject, read, do not see the problems, but tests need to conduct

ZS: here in general what I want to get... well, sort of a universal list:

1. in which class structures can be added immediately at creation (implemented - checked my example data.AddValue(new CData(i,i*2.0)) - OK)

2. in which you can write to and read from "DB" file (started writing, so far the template constructor is

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

work without writing/reading to file #1 and #2 read the database when the CDataBase is created from the disk and write to the disk when the destructor is called

....

ZS:

what's the point of all this? -I just write EAs according to a standard scheme - a magician and all manipulations with orders through searching for an order with a magician, if the TS is not "101 indicator" but more complicated, usually 2 magicians are enough, but if the TS is monitoring 80 pending orders (10 grids of orders, the grids are reopened and ... To be honest it is absurd but I have encountered it for the second time), then I start using various tricks - leading 80 orders on 80 generated magicians ))) - I got out of it, but I do not like it all

I would like to finally create a small database where I would be able to write data on orders (everything else) and, most importantly, not to pay attention to the database itself - access as toarray elements, read and write to a file when the EA is opened or closed

so on and so forth ))))


fxsaber:

SZZ It's easier to write

Then you don't need a constructor/destructor. The new/delete should be used where it's really useful. For the rest, you can do what you did with FILE above.

Thank you, but I still need to think about it ... or rather I want to do it in such a way that I won't have to think about it later))) - when OnInit() creates the database, it reads the file and DeInit() kills the database, it saves the file and if you missed delete in DeInit(), the terminal will make a note about it in the journal... In my opinion it excludes errors when working with the database... in general, if I do it, I will see how convenient it is

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

if you don't mind, why use " :: "https://www.mql5.com/ru/docs/basis/operations/other

 
Igor Makanu:

if you don't mind, why do we use " :: " here?

Otherwise I have to check that the parent classes don't have a method with the same name. And even if there isn't, if someone adds it, the code will still work.

For the same reason I always use this for unambiguity and readability.


ZZY But in some rare situations :: and this take away flexibility. There are similar subtleties about when it's better to write method body inside the class and when it's better to write it outside. I remember encountering all this, but I won't give examples.

 
fxsaber:

Otherwise I have to check that the parent classes don't have a method with the same name. And even if there isn't, if someone adds it, the code will still work.

For the same reason I always use this for clarity and readability.

Yes, it's really practical and prevents bugs, I'll take it into account

Thank you!

 
Igor Makanu:

4. if file writeflag m_fsave is active, then each time we call AddValue() method - we add more data to the file

Look at CList record format. You are ignoring it.