MQL5中的OOP问题 - 页 22

 
Vladimir Simakov:

1.new操作符 返回一个指针,当然,开发者用隐式解引用的方式搞得一团糟,所以你的版本可以用,但最好不要纠结于无文档的东西。

2.当然,我们没有C++,但它非常相似,所以初始化列表(我不知道效率如何)是合适的。

检查过了,是的,你的选项是有效的,而且从逻辑上说,它更正确。

interface IStrategy
  {
   void Algorithm()  { Print("Это не должно вызываться!!!"); }
  };
//+------------------------------------------------------------------+
class Strategy_1 : public IStrategy
  {
public:
                     Strategy_1()   { Print(__FUNCTION__); }
   void              Algorithm()    { Print(__FUNCTION__); }
  };
//+------------------------------------------------------------------+
class Strategy_2 : public IStrategy
  {
public:
                     Strategy_2()   { Print(__FUNCTION__); }
   void              Algorithm()    { Print(__FUNCTION__); }
  };
//+------------------------------------------------------------------+
class Context
  {
public:
   IStrategy         *s;
                     Context(IStrategy *_strategy) { Print(__FUNCTION__); s = _strategy;              }
                    ~Context()                     { delete s;                                        }
   void              GetStrategy()                 { s.Algorithm();                                   }
  };
//+------------------------------------------------------------------+
Context c1(new Strategy_1);
Context c2(new Strategy_2);
//+------------------------------------------------------------------+
void OnStart()
  {
   c1.GetStrategy();
   c2.GetStrategy();
   
   c1.s.Algorithm();
  }
//+------------------------------------------------------------------+

2019.08.31 22:07:35.196 tst (EURUSD,H1) Strategy_1::Strategy_1

2019.08.31 22:07:35.196 tst (EURUSD,H1) Context::Context

2019.08.31 22:07:35.196 tst (EURUSD,H1) Strategy_2::Strategy_2

2019.08.31 22:07:35.196 tst (EURUSD,H1) Context::Context

2019.08.31 22:07:35.196 tst (EURUSD,H1) Strategy_1::Algorithm

2019.08.31 22:07:35.196 tst (EURUSD,H1) Strategy_2::Algorithm

2019.08.31 22:07:35.197 tst (EURUSD,H1) Strategy_1::Algorithm

指针和初始化时创建的对象没有丢失,接口中的方法也没有取代类1和类2的方法--一切似乎都按计划进行。

 

如何在初始化过程中避免重复的代码部分? - 在构造函数中,你不能

class MyClass
{
   public:
      MyClass()         {Print("Create MyClass");}
};

interface IStrategy
  {
   void Algorithm()  { Print("Это не должно вызываться!!!"); }
  };
//+------------------------------------------------------------------+
class Strategy_1 : public IStrategy
  {
  private:
  MyClass   *m;
public:
                     Strategy_1()   { Print(__FUNCTION__); }
   void              Algorithm()    { if(m==NULL) m = new MyClass; else { } } 
  };
//+------------------------------------------------------------------+
class Strategy_2 : public IStrategy
  {
  private:
  MyClass   *m;
public:
                     Strategy_2()   { Print(__FUNCTION__); }
   void              Algorithm()    { if(m==NULL) m = new MyClass; else { } }
  };
//+------------------------------------------------------------------+
class Context
  {
private:
   IStrategy         *s;
public:
                     Context(IStrategy *_strategy) { Print(__FUNCTION__); s = _strategy;              }
                    ~Context()                     { delete s;                                        }
   void              GetStrategy()                 { s.Algorithm();                                   }
  };
//+------------------------------------------------------------------+
Context c1(new Strategy_1);
Context c2(new Strategy_2);
//+------------------------------------------------------------------+
void OnStart()
  {
   c1.GetStrategy();
   c2.GetStrategy();
  }
//+------------------------------------------------------------------+
 
Igor Makanu:

如何在初始化过程中避免重复的代码部分?- 在构造函数中,你不能

你要做的不是接口,而是一个普通的类。你把*m放在那里,做一个bool SomeMethod {if(CheckPointer(m)) return false; m=new...; return true;}
在算法中,如果(SomeMethod())...。
 
Vladimir Simakov:
你不做接口,而做一个普通的类。你把*m放在那里,并使方法成为bool SomeMethod {if (CheckPointer(m)) return false; m=new...; return true;}。
在算法中,如果(SomeMethod())...。

不,我需要的是interfes--我不需要在每一个tick 上拉动所有的东西,这是非常酷的--我将在每一个tick上调用一个策略--总的来说,到目前为止我喜欢所有这些的配置,似乎有必要用这种方式来解决我的问题。

class MyClass
{
   public:
      MyClass()         {Print("Create MyClass");}
};

interface IStrategy
  {
   void Algorithm()  { Print("Это не должно вызываться!!!"); }
  };
  
class CStrategy : public IStrategy
{
protected:
   MyClass  *m;
   void Init()   {  m=new MyClass; }
};
//+------------------------------------------------------------------+
class Strategy_1 : public CStrategy
  {
public:
                     Strategy_1()   { Print(__FUNCTION__); }
   void              Algorithm()    { if(m==NULL) Init(); else { } } 
  };
//+------------------------------------------------------------------+
class Strategy_2 : public CStrategy
  {
public:
                     Strategy_2()   { Print(__FUNCTION__); }
   void              Algorithm()    { if(m==NULL) Init(); else { } }
  };
//+------------------------------------------------------------------+
class Context
  {
private:
   IStrategy         *s;
public:
                     Context(IStrategy *_strategy) { Print(__FUNCTION__); s = _strategy;              }
                    ~Context()                     { delete s;                                        }
   void              GetStrategy()                 { s.Algorithm();                                   }
  };
//+------------------------------------------------------------------+
Context c1(new Strategy_1);
Context c2(new Strategy_2);
//+------------------------------------------------------------------+
void OnStart()
  {
   c1.GetStrategy();
   c2.GetStrategy();
  }
//+------------------------------------------------------------------+
 

我对我的例子进行了一些调整--它是有效的,但它应该看起来像这样。

//+------------------------------------------------------------------+
interface IStrategy
{  void Algorithm()                 {Print("Это не должно запускаться!!!"); } };
//+------------------------------------------------------------------+
class CStrategy : public IStrategy
{
protected:
   int x;
public:
   virtual void Algorithm()         {Print("Это не должно запускаться!!!"); } };
//+------------------------------------------------------------------+
class CStrategy_01:public CStrategy
{
public:
   CStrategy_01()                   {Print(__FUNCTION__);  x = 01;         }
   void Algorithm()                 {Print(__FUNCTION__,", x = ",x);       } };
//+------------------------------------------------------------------+
class CStrategy_02:public CStrategy
{
public:
   CStrategy_02()                   {Print(__FUNCTION__);   x = 02;        }
   void Algorithm()                 {Print(__FUNCTION__,", x = ",x);       } };
//+------------------------------------------------------------------+
class Context
{
private:
   IStrategy         *s;
public:
   Context(IStrategy *_strategy)    { Print(__FUNCTION__); s = _strategy;  }
   ~Context()                       { delete s;                            }
   void              GetStrategy()  { s.Algorithm();                       } };
//+------------------------------------------------------------------+
Context c1(new CStrategy_01);
Context c2(new CStrategy_02);
//+------------------------------------------------------------------+
void OnStart()
{  c1.GetStrategy();
   c2.GetStrategy(); }
//+------------------------------------------------------------------+



0 15:57:17.100 tst EURUSD,H1: CStrategy_01::CStrategy_01 0 15:57:17.100 tst EURUSD,H1: Context::Context 0 15:57:17.100 tst EURUSD,H1: CStrategy_02::CStrategy_02 0 15:57:17.100 tst EURUSD,H1: Context::Context 0 15:57:17.100 tst EURUSD,H1: initialized 0 15:57:17.100 tst EURUSD,H1: CStrategy_01::Algorithm, x = 1 0 15:57:17.100 tst EURUSD,H1: CStrategy_02::Algorithm, x = 2

但如果我删除CStrategy::Algorithm(void) 方法的主体,就 会出现一个错误:'Algorithm'--该函数 必须有一个主体

为什么是错误?- 因为我在声明CStrategy::Algorithm(void)方法时使用了虚拟修饰符

 
Igor Makanu:

我对我的例子进行了一些调整--它是有效的,但它应该看起来像这样。

但如果我删除CStrategy::Algorithm(void)方法的主体,就会出现一个错误:'Algorithm'--该函数 必须有一个主体

为什么是错误?- 因为我在声明CStrategy::Algorithm(void)方法时使用了虚拟修饰符

一个抽象的方法必须在后代中实现。再一次,这里不需要接口。
 
虚拟无效Algoritm()=0。
试试这个。
 
Vladimir Simakov:
虚拟无效Algoritm()=0。
试试这个。
不,这也行不通。如果你声明了一个抽象概念,请好心地实现它。
 
Vladimir Simakov:
不,这也行不通。如果你声明了一个抽象概念,请好心地实现它。

我认为编译器认为接口中的Algorithm()方法和声明的虚拟void Algorithm()是不同的方法,因为有虚拟修饰符

弗拉基米尔-西马科夫
一个抽象的方法必须在后代中实现。再一次,没有必要实施它。

我需要接口,因为我可以根据专家顾问的设置为6个策略声明不同的行为(没有那么多策略,只有订单系统的研究),这很方便。

就在此时。

class CGrid {
private:
   int               StrategyCount;
   IStrategy         *Strategy[];
public:
   CGrid(int eamagicnumber, SSettingsForOrder &settingstrategy[]);
   ~CGrid(); };
//+------------------------------------------------------------------+
void CGrid::CGrid(int eamagicnumber, SSettingsForOrder &settingstrategy[]) {
   StrategyCount = ArraySize(settingstrategy);
   ArrayResize(Strategy, StrategyCount);
   for(int i = 0; i < StrategyCount; i++) {
      settingstrategy[i].magicnumber = i+eamagicnumber;
      switch(settingstrategy[i].dealtype) {
      case NONE                  :  Strategy[i] = new CNONE(settingstrategy[i]);                   break;
      case BUY                   :  Strategy[i] = new CBUY(settingstrategy[i]);                    break;
      case ReOpenBUY             :  Strategy[i] = new CReOpenBUY(settingstrategy[i]);              break;
      case ReversBUYToSellOnly   :  Strategy[i] = new CReversBUYToSellOnly(settingstrategy[i]);    break;
      case ReversBUYAlwaysRevers :  Strategy[i] = new CReversBUYAlwaysRevers(settingstrategy[i]);  break;
      case SELL                  :  Strategy[i] = new CSELL(settingstrategy[i]);                   break;
      case ReOpenSELL            :  Strategy[i] = new CReOpenSELL(settingstrategy[i]);             break;
      case ReversSELLToBuyOnly   :  Strategy[i] = new CReversSELLToBuyOnly(settingstrategy[i]);    break;
      case ReversSELLAlwaysRevers:  Strategy[i] = new CReversSELLAlwaysRevers(settingstrategy[i]); break; } } }

我想尽量减少Algorithm()方法的主体--如果我正确地编写基类--在我的例子中是CStrategy类,那么Algorithm()本身将最多包含5-10行。


没有接口,我应该如何写这段代码?- 现在一切都很简短,只剩下拉动算法本身的策略,每一个刻度 或更少的频率。

 

как этот код без интерфейса написать? - сейчас все кратко и останется только дергать сами алгоритмы стратегий каждый тик или реже

我今晚会给你看。我现在正在用我的手机。