Fragen zu OOP in MQL5 - Seite 22

 
Vladimir Simakov:

1. new-Operator gibt einen Zeiger zurück, natürlich haben die Entwickler ein Chaos mit impliziten Dereferenzierung gemacht, so dass Ihre Version funktioniert, aber es ist besser, nicht auf undokumentierte Dinge aufhängen.

2. Natürlich haben wir nicht C++, aber es ist sehr ähnlich, so dass Initialisierungslisten (ich weiß nicht, über die Effizienz) koscher sind.

Überprüft, ja, Ihre Option funktioniert, und logischerweise ist sie korrekter:

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) Strategie_1::Strategie_1

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

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

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

2019.08.31 22:07:35.196 tst (EURUSD,H1) Strategie_1::Algorithmus

2019.08.31 22:07:35.196 tst (EURUSD,H1) Strategie_2::Algorithmus

2019.08.31 22:07:35.197 tst (EURUSD,H1) Strategie_1::Algorithmus

Der Zeiger und das bei der Initialisierung erzeugte Objekt sind nicht verloren gegangen, und die Methode in der Schnittstelle hat die Methoden der Klassen 1 und 2 nicht ersetzt - alles scheint wie geplant zu funktionieren

 

Wie kann ich sich wiederholende Codeabschnitte während der Initialisierung vermeiden? - im Konstruktor können Sie nicht

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:

Wie kann ich sich wiederholende Codeabschnitte während der Initialisierung vermeiden? - im Konstruktor, können Sie nicht

Anstelle der Schnittstelle machen Sie eine gewöhnliche Klasse. Man setzt *m dort ein und macht ein bool SomeMethod {if(CheckPointer(m)) return false; m=new...; return true;}
In Algoritm if (SomeMethod()) ...
 
Vladimir Simakov:
Anstelle der Schnittstelle machen Sie eine normale Klasse. Dort setzt du *m ein und machst die Methode bool SomeMethod {if (CheckPointer(m)) return false; m=new...; return true;}
In Algoritm if (SomeMethod()) ...

Nein, ich brauche die interfes - es ist sehr cool, dass ich nicht brauchen, um alles bei jedem Tick zu ziehen - ich werde einen Aufruf einer Strategie pro einen Tick machen - im Allgemeinen Ich mag Konfiguration von all dies so weit, es scheint, es war notwendig, um mein Problem auf diese Weise zu lösen:

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

Ich habe mein Beispiel ein wenig verändert - es funktioniert, aber es sollte so aussehen:

//+------------------------------------------------------------------+
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

aber wenn ich den Körper der MethodeCStrategy::Algorithm(void) entferne, tritt ein Fehler auf: 'Algorithm' -die Funktion muss einen Körper haben

Warum ist es ein Fehler? - weil ich die Methode CStrategy::Algorithm(void) mit dem Modifikator virtual deklariere

 
Igor Makanu:

Ich habe mein Beispiel ein wenig verändert - es funktioniert, aber es sollte so aussehen:

aber wenn ich den Körper der Methode CStrategy::Algorithm(void) entferne, tritt ein Fehler auf: 'Algorithm' - die Funktion muss einen Körper haben

Warum ist es ein Fehler? - weil ich die Methode CStrategy::Algorithm(void) mit dem Modifikator virtual deklariere

Eine abstrakte Methode muss in den Nachfahren implementiert werden. Auch hier gibt es keine Notwendigkeit für eine Schnittstelle.
 
virtual void Algoritm()=0;
Versuchen Sie dies.
 
Vladimir Simakov:
virtual void Algoritm()=0;
Versuchen Sie dies.
Nein, auch das wird nicht funktionieren. Wenn Sie eine Abstraktion deklarieren, seien Sie so freundlich, sie auch zu implementieren.
 
Vladimir Simakov:
Nein, auch das wird nicht funktionieren. Wenn Sie eine Abstraktion deklarieren, seien Sie so freundlich, sie zu implementieren.

Ich denke, dass der Compiler die Methode Algorithm() aus der Schnittstelle und die deklarierte virtuelle void Algorithm() wegen des virtuellen Modifikators als unterschiedliche Methoden ansieht

Wladimir Simakow:
Eine abstrakte Methode muss in Nachkommen implementiert werden. Noch einmal: Es besteht keine Notwendigkeit, sie zu implementieren.

Ich brauche Schnittstellen, weil es für mich bequem ist, unterschiedliches Verhalten für 6 Strategien abhängig von den Einstellungen des Expert Advisors zu deklarieren (es gibt nicht so viele Strategien, aber die Forschung der Auftragssysteme)

gerade jetzt:

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

Ich möchte den Hauptteil der Algorithm()-Methoden minimieren. Wenn ich die Basisklasse richtig schreibe - in meinem Beispiel die Klasse CStrategy -, dann wird der Algorithmus() selbst höchstens 5-10 Zeilen enthalten


Wie soll ich diesen Code ohne eine Schnittstelle schreiben? - Jetzt ist alles kurz und es wird nur noch übrig sein, die Algorithmen selbst Strategien jeden Tick oder weniger häufig zu ziehen

 

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

Ich werde es dir heute Abend zeigen. Ich bin gerade an meinem Telefon.