MQL5中的OOP问题 - 页 16

 
Dmitry Fedoseev:

标准库 假设控件是在一个表单上创建的。他们根本就不应该工作,就像这样。至少,过去是这样的。

我得试试Kajarski的GUI系列的最新版本。这对他来说是多么快速的工作。然后再写信给开发商,让他们调整自己的脑洞。
 
Vasiliy Pushkaryov:
我将不得不尝试Kajarsky关于GUI的系列文章的最新版本。这对他来说是多么快速的工作。然后再一次写信给开发者,让他们调整自己的脑洞。

每个人都在同一个圈子里行走!)))- 正是从这一系列关于图形界面 的文章中,我开始研究MQL的能力....。- 体验并不好,文章中的一些例子已经不能编译了,作者一直保持着联系,但是库的规模非常大,我还没有开始使用这个库,虽然你可能会在其中取得成功。

我认为--你要么学习一个星期的C#--你在网上有很多例子,而且VS中的表单设计器和Delphi中的一样(我之前在Delphi中写过),要么就使用SB--至少它有开发者的支持。

 
Igor Makanu:

每个人都在同一个圈子里行走!)))- 正是从这一系列关于图形界面的文章中,我开始研究MQL的能力....。- 体验并不好,文章中的一些例子已经不能编译了,作者一直保持着联系,但是库的规模非常大,我还没有开始使用这个库,虽然你可能会在其中取得成功。

我认为,或者学习C#一个星期--你在网上有很多例子,而且VS中的表单设计器与Delphi中的一样(在Delphi中我早写过),或者使用SB都一样--至少它有开发者的支持。

很遗憾听到图书馆已经被包起来了。一年多前我试过,我喜欢这个面板的外观。我甚至为MT4调整了它,并进行了尝试(由于Canvas的不同,它也没有立即编译)。 但后来,由于难以为我的任务移植它,我把SB。我想我以后会回到GUI 上来。

我不认为我可以在一周内掌握C#。但我必须给自己设定一个目标,此外,已经有了对.NET库的本地支持。在这里,你已经建议如何将其用于你的特定任务。

 
Vladimir Simakov:

而在第二种情况下,你需要

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

不知道为什么,它在你的版本中不起作用,也许我又搞砸了 )),

我想把数据保存在一个没有中间指针的列表中,这样就可以了,而且没有内存泄漏。

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

这只是我想法的开始

我想在我的模板中实现对二进制文件的写入和读取(虽然我也可以对文本文件这样做,但这并不重要)。 我不知道如何使用类字段的模板将CD数据写入文件 - 但我真的想这么做

 
Igor Makanu:

我想在我的模板中实现对二进制文件的写入和读取(尽管可以写入文本文件--这并不重要),我不知道如何使用模板将CData字段写入文件--但我真的想这么做!;)

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

我从来没有接触过CList和CObject,但来源很简单(顺便说一下,有一个虚拟的方法Save没有修改器const,不知为什么),所以一下子就解决了。


SZY 这样写比较容易。

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

那么你就不需要构造器/析构器了。在真正有用的地方使用new/delete是有意义的。否则你可以像上面的FILE那样做。

 
fxsaber:

从未使用过CList和CObject,但源代码很简单,所以马上就能用了。

哦!你这么快就得到了答案。- 谢谢你!- 晚上我就有事情做了。

我也将CList和CObject作为源码,阅读后,没有发现问题,但需要进行测试

ZS:在这里,我想得到的一般是......。某种程度上是一个通用的列表。

1.其中的类结构 可以在创建时立即添加(已实现--检查我的例子 data.AddValue(new CData(i,i*2.0))- 好的)

2.在其中你可以写入和读出 "DB "文件(开始写入,到目前为止模板构造器是

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

在不写/读文件的情况下工作,#1和#2在CDataBase从磁盘创建时读取数据库,在调用析构器时写入磁盘

....

ZS。

这一切的意义何在?-我只是根据一个标准的方案来写EA -一个魔术师和所有与订单的操作通过搜索一个魔术师,如果TS不是 "101指标 "而是更复杂的,通常2个魔术师就足够了,但如果TS是监测80个挂单(10个网格的订单,网格被重新打开,...说实话这很荒唐,但我已经第二次遇到了),然后我开始使用各种技巧--在80个生成的魔术师身上引导80个订单))。- 我摆脱了它,但我不喜欢这一切

我想最终创建一个小型数据库,在那里我将能够写入订单的数据(其他一切),最重要的是不需要关注数据库本身--对数组元素 的访问,在EA打开或关闭时读写文件。

诸如此类 ))))


fxsaber:

SZZ 写起来比较容易

那么你就不需要构造器/析构器了。新/删除应该用在真正有用的地方。对于其余的,你可以像上面的FILE那样做。

谢谢你,但我还是需要考虑一下......或者说我想以这样的方式来做,以后就不用考虑了)))。- 当OnInit()创建数据库时,它读取文件,DeInit()杀死数据库,它保存文件,如果你在DeInit()中错过了删除,终端会在日志中做一个注释...在我看来,它排除了使用数据库时的错误...一般来说,如果我这样做,我将看到它有多方便

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

如果你不介意,为什么要用" :"https://www.mql5.com/ru/docs/basis/operations/other

 
Igor Makanu:

如果你不介意的话,为什么我们在这里使用"::"?

否则我就得检查父类是否有同名的方法。即使没有,如果有人添加它,代码仍然可以工作。

出于同样的原因,我总是使用这种方式,以达到不含糊和可读性。


ZZY 但在一些罕见的情况下 ::,这就剥夺了灵活性。关于什么时候把方法体写在类里面比较好,什么时候把它写在外面比较好,也有类似的微妙之处。我记得遇到过这些事,但我不会举例。

 
fxsaber:

否则我就得检查父类是否有同名的方法。即使没有,如果有人添加它,代码仍然可以工作。

出于同样的原因,我总是用这种方式来提高清晰度和可读性。

是的,这真的很实用,而且可以防止bug,我会考虑的。

谢谢你!

 
Igor Makanu:

4.如果 文件写入标志 m_fsave是激活的,那么每次我们调用AddValue()方法时--我们将更多的数据添加到文件。

看一下CList记录格式。你在忽视它。