MQL4でシングルトンパターンを実装することは可能ですか? - ページ 9

 
hoz:

私はこのようにしました。

しかし、なぜかコンパイル時にエラーが多発します。どうしたんですか?

Myersによるかなり単純なSingletonをMQL4+に転送しようとすると、例えば次のようになります。

#property strict

/******************************************************************************/
class Symbol_Properties {
private:
   // Реализация технической части singleton'а
  /******************************************************************************/
public: // Вечно в этом MQL4++ что-то не работает: 'Symbol_Properties::Symbol_Prope…' - cannot call private member function
  Symbol_Properties() {};
private: // Восстанавливаем private
  Symbol_Properties(const Symbol_Properties &p);
  void operator =(const Symbol_Properties &);

public:
  static Symbol_Properties *singleton() {
    static Symbol_Properties sp;
    return GetPointer(sp);
  }

  // Пользовательская часть singleton'а
  /******************************************************************************/
  datetime    gdt_Quote;           // Время поступления последней котировки
  double      gda_Price [2];       // Текущие рыночные цены (0 - Bid, 1- Ask)
  double      gd_Spread;           // Размер спреда в пунктах
  double      gd_Swap;             // Своп
  double      gd_Comission;        // Комиссия
  double      gd_Pt;               // Величина одного пункта
  int         gi_Digits;           // Количество знаков в цене после запятой
  int         gi_StopLevel;        // Минимально-допустимый уровень стоп-лосса/тейк-профита в пунктах
  int         gi_FreezLevel;       // Уровень заморозки ордеров в пунктах
};

/******************************************************************************/
void change() {
  Symbol_Properties *p = Symbol_Properties::singleton(); // Получение singleton'а

  p.gdt_Quote = TimeCurrent();
  p.gda_Price[0] = Bid;
  p.gda_Price[1] = Ask;
}

/******************************************************************************/
void OnStart() {
  Symbol_Properties *p = Symbol_Properties::singleton(); // Получение singleton'а

  Print("gdt_Quote = ", p.gdt_Quote, ", Price = ", p.gda_Price[0], "/", p.gda_Price[1]);
  change();
  Print("gdt_Quote = ", p.gdt_Quote, ", Price = ", p.gda_Price[0], "/", p.gda_Price[1]);
}

実行結果です。

01:24:57 Script 3 EURUSDm,H1: loaded successfully
01:24:57 3 EURUSDm,H1: initialized
01:24:57 3 EURUSDm,H1: gdt_Quote = 1970.01.01 00:00:00, Price = 0.0/0.0
01:24:57 3 EURUSDm,H1: gdt_Quote = 2014.09.03 21:24:57, Price = 1.31461/1.3148
01:24:57 3 EURUSDm,H1: uninit reason 0
01:24:57 Script 3 EURUSDm,H1: removed

静的メソッド singleton() は Symbol_Properties 型の静的変数を 作成しますが、コンパイル時に NOT valid default constructor call access error が生成されます。そのため、MQL4+の実装のバグにより、このコンストラクタはpublicに配置される必要がありました。修正されれば、もうやらなくていいんです。

実行結果は、change()呼び出し後にデータが変更されたことを示しています。これは、change()関数がOnStart()で受信したものと同じオブジェクトのアドレスを自身の内部で受信したことを間接的に示している。

MQL4+のエラーにより、これはシングルトンではなく、デフォルトのコンストラクタがパブリックであるため、このようなオブジェクトを多数作成することが可能です。この誤りを修正し、デフォルトコンストラクタをprivateセクションに配置すれば、MQL4+におけるMyersのSingletonの本格的な実装となります。

 
ALXIMIKS:

スタティックとクラスでスタティックの挙動が 異なることを2日で理解しなかったのか?

の構造は、cから引用し、継承の面で少しばかり汲み上げたもののようです。

授業に関しては、本格的なものです。

このため、構造体の中にスタティック変数のための領域を確保する必要はありません。

が、授業は予約しないとできない。

そんなことはありません。この素晴らしいMQL4+コンパイラは、異なる挙動をします。オブジェクトのインスタンスを作成すると同時に、挙動が「整列」します。

#property strict

/******************************************************************************/
struct A {
  static int x;
};

/******************************************************************************/
void OnStart() {
  A y;
}

なぜかコンパイルできません(1番目と3番目は警告ですが、2番目は本格的なエラーです)。

struct has no members, size assigned to 1 byte
unresolved static variable 'A::x'
variable 'y' not used

では、構造体の中に「スタティック変数のための空間」を確保する必要があるのでしょうか?

そして、次のバージョンのターミナル/コンパイラでは - 同じになるのでしょうか(まあ、バージョンを変更するときに、前に書いたものをすべて急いで修正することはありませんが)。

 
TheXpert:

カプセル化のことを忘れていました。そして、それは削除することができます。また、ここには定数ポインタがありません)。実は、シングルトンは最適なパターンではありません。

そして、テンプレートは、少なくともいくつかは良いものです。クラスにとっては、おそらく夢でしかないでしょう。



まあ、最悪だろうが最高だろうが、私は判断しません。

この議論に参加された方々に、上記のMEMORY MANAGEMENT MODES - Automatic, Dynamic, Static, Based - は、どんなにOOPが強力でも、テンプレートには適用されないということを思い出していただきたいのです。

 
Так обязательно ли резервировать в структурах "место под static-переменную"?
"Yes "なら、"No "もできるけど、そういうやり方はしない方がいいという点です。
 
simpleton:


さて、MQL4+のバグのため、デフォルトのコンストラクタがpublicであるため、このようなオブジェクトを多数作成することができ、これはSingletonではありません。この誤りを修正し、デフォルトコンストラクタをprivateセクションに配置すれば、MQL4+の本格的なSingleton実装となります。


ありがとうございます!ここでポインターを取ることができるなんて知りませんでした。

コードがぐちゃぐちゃで、もっとシンプルにできるはずです。テンプレートがないのが残念です。

コードが入れ られない((

class Singleton{

プライベート

class SomeClass{

を公開します。

int a;

};

シングルトン(){}

~シングルトン(Singleton){}。

を公開します。

static SomeClass* インスタンス(){...

static SomeClass a();

return GetPointer (a);

}

};

void OnStart()

{

SomeClass* some_ptr = Singleton::Instance()です。

some_ptr.a = 5;

Alert(some_ptr.a)です。

}

 
ALXIMIKS:


ありがとうございます、ここでポインターを取れるとは知りませんでした。

コードをいじっているのだから、もっとシンプルにできるはずだ。テンプレートがないのが残念だ。

コードがうまくいかない((

class Singleton{

プライベート

class SomeClass{

を公開します。

int a;

};

シングルトン(){}

~シングルトン(Singleton){}。

を公開します。

static SomeClass* インスタンス(){...

static SomeClass a();

return GetPointer (a);

}

};

void OnStart()

{

SomeClass* some_ptr = Singleton::Instance()です。

some_ptr.a = 5;

Alert(some_ptr.a)です。

}

以下は、MyersのC++用コードです。

class Singleton
{
private:
    Singleton() {}
    Singleton( const Singleton&);
    Singleton& operator=( Singleton& );
public:
    static Singleton& getInstance() {
        static Singleton  instance;
        return instance;
    }
};

そして、同じコードをMQL4+に移し替えたものが、例のクラスの技術的な部分です。

class Symbol_Properties {
private:
   // Реализация технической части singleton'а
  /******************************************************************************/
public: // Вечно в этом MQL4++ что-то не работает: 'Symbol_Properties::Symbol_Prope…' - cannot call private member function
  Symbol_Properties() {};
private: // Восстанавливаем private
  Symbol_Properties(const Symbol_Properties &p);
  void operator =(const Symbol_Properties &);

public:
  static Symbol_Properties *singleton() {
    static Symbol_Properties sp;
    return GetPointer(sp);
  }

どこが "魔法使い "なのか?

特にOnStart()でのSomeClass型の使用は不適切で、これはSingletonクラスの入れ子型であり、「大人の」コンパイラは即座にエラーを検出します。

try.cpp:33:9: error: unknown type name 'SomeClass'
        SomeClass* some_ptr = Singleton::Instance();
        ^

しかし、入れ子の型は正しく指定できるため、この点は重要ではありません。さらに重要なことは、SomeClass 型は Singleton クラスの private セクションで宣言されているため、OnStart() で SomeClass を使うことは根本的に間違っており、「大人の」コンパイラはすぐにそれを報告することである。

try.cpp:33:20: error: 'SomeClass' is a private member of 'Singleton'
        Singleton::SomeClass* some_ptr = Singleton::Instance();
                   ^

MQL4+コンパイラがアクセス制御のバキバキを修正しない限り、あなたの実装はうまくいくでしょう。

 

1.マエアセ、じゃなくて、MQLで コードがエラーなく動いて正しい 動作を するのと、+αでないのと、どっちが大事なんだ。

2.あなたのコードは、あるべき姿になっていますか?いいえ、そんなことはありません。あなたはもうすべてを理解している。

私の例は、MQLにおける(C++に関する)エラーの処理を示しています。 何か都合の悪いことがあれば、ポイント1、2をご覧ください。

4.プライベートクラスへのポインタの作成については、たしかにMQLのエラーになりますが、型を特定するためのオートがないので、動作するのは良いことです。\

(追記)オートマを犠牲にしてやりすぎたかもしれない、確認すべき)

5.MQLでは、オブジェクトを取得するためにポインタをデリファレンスする方法は見つかっていません。したがって、プライベートコピーコンストラクタと代入演算 子は余計なものだと考えています。

使ってみてください、道が見えてくると嬉しいです))

 
ALXIMIKS:

1.マエアセじゃなくて、MQLでエラーなく 動作し、やるべき ことをやって いるコードが+αでないのは、一体どうしたことでしょう。

2.あなたのコードは、あるべき姿になっていますか?いいえ、そんなことはありません。あなたはもうすべてを理解している。

私の例は、MQLにおける(C++に関する)エラーの処理を示しています。 何か都合の悪いことがあれば、ポイント1、2をご覧ください。

4.プライベートクラスへのポインタの作成については、たしかにMQLのエラーになりますが、型を特定するためのオートがないので、動作するのは良いことです。\

(追記)オートマを犠牲にしてやりすぎたかもしれない、確認すべき)

5.MQLでは、オブジェクトを取得するためにポインタをデリファレンスする方法は見つかっていません。したがって、プライベートコピーコンストラクタと代入演算子は余計なものだと考えています。

使ってみてください、道が見えてくると嬉しいです))

1.しかし、その方法はありません(以下に説明します)。

2.直さないのなら......どっちもダメでしょう。そして、まったく実行できそうにない。

3.バグを回避するのではなく、搾取する。

4.ないものがたくさんあるんです。

5.そのようなことは今回のバージョンでは可能かもしれません、特に、コピーコンストラクタは合成されないとフラッシュしたように思いますが、だからといって、今後のバージョンで合成を開始しないとは言い切れません。一方、宣言することによるオーバーヘッドは、無視できるほど小さいと思います。

さて、あなたのコードが、前の投稿で述べたような潜在的な問題を抱えているだけでなく、なぜ原理的にシングルトンでなく、そうならないのか、そして、アクセスバッカンを修正するかどうかについても説明します。

#property strict

class Singleton{
private:
         class SomeClass{
         public:
            int a;
         };
        Singleton(){}
        ~Singleton(){}   
public:
        static SomeClass* Instance(){
                        static SomeClass a;
                        return GetPointer (a);
                }
        };
        int i;

void OnStart()
{       
        SomeClass* some_ptr = Singleton::Instance();
        SomeClass obj1;
        SomeClass obj2;

        obj1.a = 3;
        obj2.a = 7;

        some_ptr.a = 5;
        Print("some_ptr.a = ", some_ptr.a);          
        Print("obj1.a = ", obj1.a);          
        Print("obj2.a = ", obj2.a);          
}

このコードはかなり正常に実行されています。

10:09:27 Script 3 EURUSDm,H1: loaded successfully
10:09:27 3 EURUSDm,H1: initialized
10:09:27 3 EURUSDm,H1: some_ptr.a = 5
10:09:27 3 EURUSDm,H1: obj1.a = 3
10:09:27 3 EURUSDm,H1: obj2.a = 7
10:09:27 3 EURUSDm,H1: uninit reason 0
10:09:27 Script 3 EURUSDm,H1: removed

シングルトンがいくつもできて、しかもONCEが存在するのがわかりますか?

この意味で、アクセスバッカンが修正されたら、あなたのコードは何か変わるのでしょうか?

私のコードで変わるのでしょうか?

堂々と言えば言うほど、真実味が増すと思いませんか?

 

はい、ご指摘ありがとうございます。おっしゃるとおり、このバリアントでもシングルトンではありません。

暗黙のコンストラクタと演算子について - 明示的にして使ってみると、オブジェクトへのポインタの参照解除ができないため、うまくいかないようです。

なぜうまくいかないのか、'ptr' - protected memberfunction を呼び出すことができない :

class smart_ptr{
            Singleton* ptr;
      public:        
            smart_ptr(Singleton* val): ptr(val){}          
            smart_ptr(): ptr(NULL){} 
            ~smart_ptr(){delete ptr;}
      };
 
ALXIMIKS:

はい、ご指摘ありがとうございます。おっしゃるとおり、このバリアントでもシングルトンではありません。

暗黙のコンストラクタと演算子について - 明示的にして使ってみると、オブジェクトへのポインタの参照解除ができないため、うまくいかないようです。

なぜうまくいかないのか、'ptr' - protected member function を呼び出すことができない :

うまくいかないようで、この他にもたくさんのバグがあります。それに気づく人がほとんどいないのが残念です。議論をするつもりはありませんが、実は大きな違いがあるのです。C++で構造体に適用されるものが、MKL4では機能しないことがあります。でも、黙ってようか......そうしないと、こんな質問をされるようになるんだ。

"なぜ必要なのか "を考える

未完成の教科書に手を出すことなく、単純にMKL4のC++で動くものを書いて、それがここで動くかどうかは考えないようにするためだけならね。現段階では他に何も必要ないのですが...。