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;}を作る。
アルゴリズムで if (SomeMethod()) ...
 
Vladimir Simakov:
インターフェイスの代わりに、普通のクラスを作るのです。そこに*mを置き、bool SomeMethod {if (CheckPointer(m)) return false; m=new...; return true;}とするのである。
アルゴリズムで 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' -the function must have the body

なぜエラーになるのですか?- CStrategy::Algorithm(void) メソッドを修飾子 virtual で宣言しているからです。

 
Igor Makanu:

私の例を少し微調整してみました - うまくいきましたが、次のように見えるはずです。

しかし、CStrategy::Algorithm(void) メソッドのボディを削除すると、次のようなエラーが発生します: 'Algorithm' -the function must have body

なぜエラーになるのですか?- CStrategy::Algorithm(void) メソッドを修飾子 virtual で宣言しているからです。

抽象的なメソッドは、子孫に実装されなければならない。もう一度言いますが、ここにインターフェースは必要ありません。
 
virtual void Algoritm()=0;
これを試してみてください。
 
Vladimir Simakov:
virtual void Algoritm()=0;
これを試してみてください。
いいえ、それもダメです。抽象化を宣言したなら、それを実装するくらいの親切心が必要です。
 
Vladimir Simakov:
いいえ、それもダメです。抽象化を宣言したなら、それを実装するくらいの親切心が必要です。

virtual修飾子があるため、コンパイラはインターフェイスにあるAlgorithm()メソッドと宣言されたvirtual void Algorithm()を別のメソッドとして認識していると思います。

ウラジミール・シマコフ
抽象的なメソッドは、子孫に実装する必要があります。もう一度言いますが、実装する必要はありません。

Expert Advisorの設定によって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行程度になるだろう。


インターフェイスがない場合、このコードはどのように書けばいいのでしょうか?- 今はすべてが簡潔で、アルゴリズム自体の戦略を1ティックごと、あるいはそれ以下の頻度で引っ張ることしか残されていないでしょう。

 

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

今夜、お見せします。今、携帯電話からです。