Вопросы по ООП в MQL5 - страница 22

 
Vladimir Simakov:

1. Оператор new возвращает указатель, разрабы конечно намудрили с неявными разыменовываниями, поэтому твой вариант и работает, но лучше уж на недокументированные вещи не завязываться.

2. У нас конечно не С++, но очень похоже, поэтому списки инициализации (не знаю насчет эффективности) это кошерно.

проверил, да работает Ваш вариант, и по логике он более правильный:

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:

как избежать повторяющихся участков кода при инициализации? - в конструкторе нельзя

Вместо interface  делаешь обычный класс. Туда помещаешь *m и делаешь в нем метод bool SomeMethod {if (CheckPointer(m)) return false; m=new...; return true;}
В Algoritm if (SomeMethod()) ...
 
Vladimir Simakov:
Вместо interface  делаешь обычный класс. Туда помещаешь *m и делаешь в нем метод bool SomeMethod {if (CheckPointer(m)) return false; m=new...; return true;}
В Algoritm if (SomeMethod()) ...

нет, интерфес нужен - очень классно получается что не нужно будет на каждом тике все дергать - сделаю по одному вызову одной стратегии на один тик - в общем пока нравится мне конфиг всего этого, кажется так нужно было мою проблему решать:

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' - function must have a body

почему ошибка? - ведь объявляю метод CStrategy::Algorithm(void)  с модификаторм virtual

 
Igor Makanu:

немного подправил свой пример - все работает, но по моему должно так выглядеть это:

но почему то если уберу тело метода CStrategy::Algorithm(void) - то будет ошибка: 'Algorithm' - function must have a body

почему ошибка? - ведь объявляю метод CStrategy::Algorithm(void)  с модификаторм virtual

Абстрактный метод обязателен к реализации в наследниках. Еще раз говорю, ни к чему здесь interface.
 
virtual void Algoritm()=0;
Так попробуйте
 
Vladimir Simakov:
virtual void Algoritm()=0;
Так попробуйте
Не, тоже не пойдет. Если абстракцию объявили, то будте добры реализовывать.
 
Vladimir Simakov:
Не, тоже не пойдет. Если абстракцию объявили, то будте добры реализовывать.

по моему просто компилятор воспринимает метод Algorithm() из интерфейса и объявленную  virtual void Algorithm()  как разные методы из за модификатора  virtual

Vladimir Simakov:
Абстрактный метод обязателен к реализации в наследниках. Еще раз говорю, ни к чему здесь interface.

интерфейсы нужны, мне удобно в зависимости от настроек советника обьявлять разные поведения для 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() - если правильно напишу базовый класс - в моем примере выше class CStrategy , то в самих Algorithm()  будет ну строк по 5-10 не более


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

 

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

Вечером покажу. Сейчас с телефона.
Причина обращения: