OOPに関するヘルプ

 

こんな授業を作っています。

class Strategy1
{
        Strategy1();
 };

class Strategy2
{
        Strategy (string sym);
}

今度は、オブジェクトの配列を呼び出したい。

Strategy1 S[10];  // компилируется 
Strategy2 Z("EURUSD")[10]; // не компилируется 

コンストラクタにグローバルレベルのパラメータがある場合、オブジェクトの配列を素早く作成するにはどうしたらよいでしょうか。

例えば?コンストラクタを変更して先にオブジェクトを作成し、OnInitでオブジェクトをシンボルに置き換えるにはどうすればいいのでしょうか?

もっと簡単な方法があるのでは?

 

個人的には、このような場合、オブジェクトのInit()関数を使います。

まず、配列を作成し、配列内のすべてのオブジェクトに対してInit()関数を呼び出し、そこですべてのパラメータを設定できるようにします。

別の関数で初期化すると、オブジェクトの再初期化が可能になり、コンストラクタで初期化すると、オブジェクトの再初期化ができなくなる。

 
Georgiy Merts #:

個人的には、このような場合、オブジェクトのInit()関数を使います。

まず、配列を作成し、配列内のすべてのオブジェクトに対してInit()関数を呼び出し、そこですべてのパラメータを設定できるようにします。

別の関数で初期化することでオブジェクトの再初期化が可能になり、コンストラクタで初期化するとオブジェクトの再初期化ができなくなる。

まあ、そんなイメージです。ありがとうございます。

 

もう1点。オブジェクトの配列はポインタで作成するのがよいでしょう。そうしないと、スタック・メモリに配列ができてしまい、非常に小さくなってしまいます。

Strategy2 *pZ[]; 
if (ArrayResize(pZ, 10) != 10)
{
   Alert("Memory allocation error");
   return;
}

for (int i = 0; i < 10; ++i)
{
   pZ[i] = new Strategy2("EURUSD"); 
   if (CheckPointer(pZ) == POINTER_INVALID)
   {
      Alert("Class instantiation error");
      return;
   }
}
 
Ihor Herasko #:

もう1点。オブジェクトの配列はポインタで作成するのがよいでしょう。そうでなければ、スタック・メモリに非常に少ない配列が得られます。

想定される問題の例があればいいと思います。

 
Ihor Herasko #:

もう1点。オブジェクトの配列はポインタで作成するのがよいでしょう。さもないと、スタック・メモリに非常に小さな配列が作成されます。

痛そう。

 
大したことではありません。
 
fxsaber #:

潜在的な問題の例があればよい。

問題ではないし、潜在的な問題であることは確かです。MTのメモリ操作のクセが出ただけです。ここでは、静的な配列を示します。

#define               ARRAY_SIZE           int(60000000)
class Test
{
public:
   int               nA;
   double            fB;
   datetime          dtC;

                     Test(void)
                       : nA(0)
                       , fB(1.0)
                       , dtC(__DATETIME__)
                     {
                     };
};

Test classTest[ARRAY_SIZE];                   // 'classTest' - global variables section is too large
 
void OnStart()
{
}

そして、こちらがダイナミックアレイ。

#define               ARRAY_SIZE           int(60000000)
class Test
{
public:
   int               nA;
   double            fB;
   datetime          dtC;

                     Test(void)
                       : nA(0)
                       , fB(1.0)
                       , dtC(__DATETIME__)
                     {
                     };
};

Test *pClassTest[];
 
void OnStart()
{
   if (ArrayResize(pClassTest, ARRAY_SIZE) != ARRAY_SIZE)
   {
      Alert("Not enought memory");
      return;
   }
   
   for (int i = 0; i < ARRAY_SIZE; ++i)
   {
      pClassTest[i] = new Test();
      if (CheckPointer(pClassTest[i]) == POINTER_INVALID)
      {
         Alert("Class instantiation error");
         return;
      }
   }

   for (int i = 0; i < ARRAY_SIZE; ++i)
      delete pClassTest[i];
}

この場合、すべてコンパイルして動作します。

 
Ihor Herasko #:

問題ではないし、ましてや潜在的な問題でもない。MTのメモリ操作のクセが出ただけです。ここでは、静的な配列を示します。

そして、こちらがダイナミックアレイ。

この場合、すべてがコンパイルされ、動作します。

スタックと何の関係があるんだ?最初のケースでは、静的に(コンパイル時に)ヒープに大きなメモリブロックを確保しようとしたため、コンパイラに額を蹴られたことになります。なぜなら、それだけのメモリを確保できるかどうか、現実にはよくわからないからです。

2つ目のケースでは、すでに実行時に大きなメモリチャンクを割り当てていることになります。そして、割り当てられるかどうかは、プログラムがすでにマシンの特定のリソース(メモリ)を使って動作しているため、すぐにわかるようになっています。

また、ポインターは何の関係があるのでしょうか?mqlの配列には、コンパイル時に定義されるものと、ダイナミックに定義されるものがあります。ポインタ * だけでなく、通常のクラスフィールドも動的配列を指すことができる。だから、ここでポインターを使うのは絶対に正当化できない。

ポインタ、クラス、マクロなど、コードの印象がおかしく、何が起こっているのか全く理解できない。

 
Ihor Herasko #:

問題ではありませんし、ましてや潜在的な問題でもありません。MTのメモリ操作のクセが出ただけです。ここでは、静的な配列を示します。

そして、こちらがダイナミックアレイ。

この場合、すべてコンパイルして動作します。

間違った例では、何も言わないコンパイラの制限で、開発者がそう決めただけです。

もし、2つのバージョンがあって、一方は大きな静的配列、もう一方は小さな静的配列で、なんと、プログラムが動作したとき、一方では、例えば、関数を再帰的に呼び出すときに問題が発生し、もう一方では、同じ条件下で問題が発生しなかったとします。その時に、結論を出すことができるのです・・・生絞りジュースの害について)))

 
Vasiliy Sokolov #:

スタックと何か関係があるのでしょうか?最初のケースでは、静的に(コンパイル段階で)ヒープに大きなメモリブロックを確保しようとしたため、コンパイラに頭を蹴られて当然です。なぜなら、現実世界では、それだけのメモリを確保できるかどうかがまったくわからないからです。

2つ目のケースでは、すでに実行時に大きなメモリチャンクを割り当てていることになります。そして、割り当てられるかどうかは、プログラムがすでにマシンの特定のリソース(メモリ)を使って動作しているため、すぐにわかるようになっています。

また、ポインターは何の関係があるのでしょうか?mqlの配列には、コンパイル時に定義されるものと、ダイナミックに定義されるものがあります。ポインタ * だけでなく、通常のクラスフィールドも動的配列を指すことができる。だから、ここでポインターを使うのは絶対に正当化できない。

ポインタ、クラス、マクロなど、コードの印象がおかしく、何が起こっているのか全く理解できない。

この例を少し変えて、ローカルに宣言し、それほどひどくない数値を入れると、コンパイラは何が問題なのかを直接教えてくれる。

#property strict
#define               ARRAY_SIZE           int(140000)

class Test
{
   
public:
   int               nA;
   double            fB;
   datetime          dtC;

                     Test(void)
                       : nA(0)
                       , fB(1.0)
                       , dtC(__DATETIME__)
                     {
                     };
};
 
void OnStart()
{
   Test classTest[ARRAY_SIZE];    // the size of local variables is too large
}
レナーテに反論することがあれば、どうぞご自由に
the size of local variables is too large (more than 512kb)
the size of local variables is too large (more than 512kb)
  • 2014.02.08
  • www.mql5.com
Здравствуйте! Написал индикатор на mql4. Все работало...
理由: