MQL5中的OOP问题 - 页 35

 
Roman:

如果对象已经完成了它的任务,为什么还要把它留在内存中?
不会出现内存泄漏吗?

它会的,特别是如果它在OnDeinit中也没有被删除。
如果你真的不需要它了,你不必把它储存在内存中。但更多的情况是,一个对象在一次迭代中被创建和使用...然后在第二次迭代时...以此类推。然后,在某些条件下,同一类别的另一个对象被创建,你已经和这个类别的两个或更多的对象一起工作,每个对象在整个EA的生命周期中都需要。

 
BlackTomcat:

它将会发生,特别是如果它在OnDeinit中也没有被删除。
如果你真的不需要它了,你不必把它储存在内存中。但更多的情况是,一个对象在一次迭代中被创建和使用...然后在第二次迭代时...以此类推。然后,在某些条件下,同一类别的另一个对象被创建,你已经和这个类别的两个或更多的对象一起工作,每个对象在整个EA的生命周期中都需要。

所以你想说,一个受控的内存泄漏比重新创建对象要好?
也就是说,节省时间,以换取被控制的守护神?
以后不失去它们是很危险的。

 

使用专家的模板https://www.mql5.com/ru/forum/85652/page24#comment_13054686 写的。

相当灵活的模板,允许在 "2次点击 "中添加不同的 "加号",而且代码可读性和逻辑性都很强,但...我回到了一些讨论过的范式,一个好的类,嗯,它不应该有静态方法

理论上听起来不错,但在实践中...在我看来,至少对于MQL-问题,我认为不是这样。

根据模板,EA类已经写好,并且在OnTick()中启动了一个公共方法。 但在EA的初始化过程中,我想检查是否有未结订单并拦截它们。

1.在OnTick()下面写一个函数,如果它通过向导找到一个开放的订单,就会创建一个EA对象;如果没有找到订单,就根据基本逻辑初始化EA对象--EA对象只在交易时间创建,在未来实现TS的逻辑。

2.在EA中编写一个静态类,它实现了项目1


从本质上讲,第1和第2项是相同的,不同的是,在第1步中,我添加了一个只有在EA初始化(第一次运行)时才有意义的函数,但我认为,它使代码过载 - 一个函数将在整个程序的执行过程中被调用一次

如果你制定了一个静态方法(pp.2),那么它将是合乎逻辑和可读的--该方法只需要用于初始化,并定义了EA对象应该被创建的时刻--你应该只向该方法发送一个神奇数字。


在我看来,禁止在方便的时候使用静态方法...说得不好听点就是错了!

 
Igor Makanu:

静态方法 与函数的区别仅在于其范围。


这种做法是危险的

input int inInput = 0;

const bool Init = EventSetTimer(1);

void OnTimer()
{
  static int Input = inInput;
  
  Print(Input);
}


如果您在EA运行时改变输入,输入将不会改变。

因此,它充满了

input long inMagic = 0;

void OnTick()
{
  static ORDER Orders[]; // Список ордеров по мэджику или что-то подобное, зависящая от входных.
}
 
fxsaber:

如果你在EA运行时改变输入,输入将不会改变。

我知道这一点,在我的TS中,你不能在EA工作时改变输入参数,运行时间与TS的逻辑是分开的。

我的问题纯粹是理论性的,我不想让代码过载,所以我在寻找在某处崩溃后恢复TS的可能性,到目前为止我看到的是这样的。

input int EAMagicNumber = 12345;
class CEA
{
public:
   static bool       NeedRecovery(int magic_)            {   return(true);    }
   bool              Recovery(int magic_,int inputparam) {   return(true);    }
                     CEA()                               {                    }
                     CEA(int inputparam)                 {                    }
                    ~CEA()                               {                    }
};

CEA *ea;

void OnStart()
{
   if(CheckPointer(ea)==POINTER_INVALID)
   {
      if(CEA::NeedRecovery(EAMagicNumber))   //если нашли открытые ордера с магиком
      {
         ea = new CEA();         // создали объект
         ea.Recovery(EAMagicNumber,11111);   // запустили восстановление ТС
      }else ea = new CEA(2222222);           //обычный запуск
   }
 
Igor Makanu

把这个逻辑塞进构造函数更有意义。

 
fxsaber:

静态方法 与函数的区别仅在于其范围。

不正确,他们还可以访问类的非公开成员和方法。
 
TheXpert:
不正确。还可以访问类的非公共成员和方法。

这里有一个术语上的误解。"可视区域 "不仅仅是指谁能看到这个方法。但也是他自己所看到的。

 
fxsaber:

这里有一个术语上的误解。

毕竟,可见性和访问是不同的概念,最好不要把它们混为一谈。
 
fxsaber:

把这个逻辑放在构造函数中更有意义。

是的,这是一个更好的解决方案!所以少了一个方法

应该是这样的。

input int EAMagicNumber = 12345;
class CEA
{
public:
   static bool       NeedRecovery(int magic_)            {   return(true);    }  //тут проверки
                     CEA(int magic_)                     {                    }  //это обычный запуск если все ОК
                     CEA(int magic_, int recoveryparam)  {                    }  //тут аварийное восстановление
                    ~CEA()                               {                    } };

CEA *ea;

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnStart()
{  if(CheckPointer(ea)==POINTER_INVALID)
   {  if(CEA::NeedRecovery(EAMagicNumber))   //если нашли откртые ордера с магиком
      {  
         ea = new CEA(EAMagicNumber,11111);  // запустили востановление ТС
      }
      else ea = new CEA(EAMagicNumber);      //обычный запуск
   } 
}
TheXpert
毕竟,可见性和访问是不同的概念,最好不要把它们混为一谈。
这就是为什么我有一个问题,我应该把检测最后一次运行崩溃的方法放在哪里,现在我的代码结构很紧凑,一切都清楚地遵循我上面显示的模式。