エラー、バグ、質問 - ページ 2657

 
Stanislav Korotky:

それが、クラスツリーには共通のノードCWndがあります(CObjectはさらに遠く、ルート)。

CButton -> CWndObj -> CWnd -> CObject.

メソッドのパラメータをCObjectに変更すると、2倍以上のエラーが発生します。

配列でない場合も、同様のクラス階層が機能します。以下は、コンパイルしたコードです。

問題は、これを配列に対しても機能させる方法です。

テンプレートが役立つのはわかるが、それだけは避けたい。

IMHOは、継承権によってテンプレートなしで動作するはずです。

C++のように確認しました。

効くんです。しかし、MQLはそれを消化しないのです。インデックスがある場合もない場合もです。

C++の場合は、お手本がより明確になります。実行して見てください)))

class CWnd
{
public:
    int x;
    CWnd(int _x = 10) : x(_x) {}
};
class CButton : public CWnd
{
    int a;
public:
    CButton(int _a=6) : CWnd(),a(_a) {}
};

class Collection
{
public:
    Collection(CWnd* ptr,size_t size) {
        for (int i = 0; i < size; cout << ptr[i++].x<<endl);
    }
};

int main()
{
    CButton buttons[10];
    CWnd wnd[10];
    Collection data1(&wnd[0],_countof(wnd));
    cout << "------------------------------" << endl;
    Collection data2(&buttons[0],_countof(buttons));
    return 0;
}
 

ああ、悪かったよ。しかし、そこで次のような疑問が湧いてくる。このC++のコードは動作します(すでに正確に動作しています;-))。

class Base
{
  public:
    virtual void method1(void) { cout << "2\n"; }
};

class Derived: public Base
{
  public:
    virtual void method1(void) override { cout << "3\n"; }
};

template<typename T>
class Wrapper
{
  public:
    Wrapper(T *ptr)
    {
      ptr->T::method1();
    }
};

int main()
{
  Derived d;
  d.Base::method1();   // ok
  Wrapper<Base> w(&d); // ok

  return 0;
}

同様のMQLでエラーが発生する。

class Base
{
  public:
    virtual void method1(void) { Print(__FUNCSIG__); }
};

class Derived: public Base
{
  public:
    virtual void method1(void) override { Print(__FUNCSIG__); }
};

template<typename T>
class Wrapper
{
  public:
    Wrapper(T *ptr)
    {
      ptr.T::method1(); // <<< 'Base' is not a class, struct or union
    }
};


void OnStart()
{
  Derived d;
  d.Base::method1();   // ok
  Wrapper<Base> w(&d); // causes the error above
 
Stanislav Korotky:

ああ、悪かったよ。しかし、そこで次のような疑問が湧いてくる。このC++のコードは動作します(すでに正確に動作しています;-))。

同様のMQLでは、エラーが発生します。

課題はわからないけど、こういうのを探しているんだろうな。

typedef void(*PTR)(void);

MQLでは、これはvoid func(void)関数へのポインタです。

は、クラス内で PTR 型のフィールドを宣言し、そこに関数を代入して、「ポインタの参照を解除」して、その関数を呼び出すことができます。

手続き型で書かれた関数をクラスに渡すことは問題なくできますが、クラスメソッドは おそらくそう簡単に渡すことはできません。

 
Igor Makanu:

タスクはわかりませんが、こんなものを探しているのではないでしょうか?

MQLでは、void func(void)関数へのポインタです。

は、クラス内でPTR型のフィールドを宣言し、そこに関数を代入して、「ポインタの参照を解除」して、その関数を呼び出すことができます。

手続き型で書かれた関数をクラスに渡すことは問題なくできますが、クラスメソッドは おそらくそう簡単に渡すことはできません。

typedef はメソッドでは動作しません。

dynamic_castは継承者(より長い連鎖)に対して働きます。つまり、baseへのポインタがdivedを含んでいる場合、divedにキャストして、それがNULLでなければ(つまり正常にキャストされていれば)、そのメソッドを呼び出すことができるのです。しかし、私の場合のように、逆に、派生するポインタがある場合は、定義上、ベースでもあるのです。そして、その仮想メソッドを呼び出すと、ポインタの中にderivedが「居座って」いることがわかり、オーバーライドされた実装が呼び出されます。ベースとなるものが必要です。

この目的のためにC++では上記のような構文がありますが、MQLはC++ではありません。どうやらまだ方法がないようです。

私は回避策を講じましたが、すべてのタスクでうまく機能するとは限りません。

このタンバリンダンスのポイントは、いつものように、絡まったコードを「ライブラリ」の中に収め、それを使うコードを明確でシンプルなものにすることです。

 

テスターのrand()を何で初期化するか?

のコードで表示されます。

input ulong param = 18446744073709551615;
void OnTick()
   {
   }
//+------------------------------------------------------------------+
double OnTester()
   {
      srand(GetTickCount()); 
      return(rand());
   }
//+------------------------------------------------------------------+

私はこういう疑似ランダム生成はあまり好きではありません。


 
Igor Makanu:

テスターのrand()を何で初期化するか?

のコードで表示されます。

私はこういう疑似ランダム生成はあまり好きではありません。


ヘルプ:MathRand

備考

この関数を初めて呼び出す前に、MathSrand を 使って疑似乱数発生器を初期状態に設定する必要があります。


MathSrandで今すぐお試しください。

Документация по MQL5: Математические функции / MathRand
Документация по MQL5: Математические функции / MathRand
  • www.mql5.com
Математические функции / MathRand - справочник по языку алгоритмического/автоматического трейдинга для MetaTrader 5
 
Vladimir Karputov:

参考:MathRand

備考

MathSrand 関数は、最初の関数呼び出しの前に使用して、疑似乱数発生器を初期状態に設定する必要があります。

キャップさん、ありがとうございます。

テスターの話です。

このコードはテスターでも動作しません。

input ulong param = 18446744073709551615;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
   {
   MathSrand(GetTickCount()); 
   return(INIT_SUCCEEDED);
   }
//+------------------------------------------------------------------+
void OnTick()
   {
   }
//+------------------------------------------------------------------+
double OnTester()
   {
      return(rand());
   }
//+------------------------------------------------------------------+
 
Igor Makanu:

テスターであれば、MathSrandを使う必要はないと思うのですが。

しかし、それで解決しない場合は、テスターがある時点でMathSrand(GetTickCount())を強制している可能性が高いです。

次に MathSrand(int(GetMicrosecondCount()%1000000)) を試してみてください。

GetTickCount()は、15.625ミリ秒ごとに値を変更することを忘れないでください。テスターとしては非常に長い時間間隔ですね。

 
Nikolai Semko:

テスターであれば、MathSrandを使う必要はないと思うのですが。

これはドキュメントと矛盾していますhttps://www.mql5.com/ru/docs/math/mathrand

最初の関数呼び出しの前に、MathSrand関数を使って、疑似乱数発生器を初期状態にする必要があります。

ソースコードは見たくないのですが、ニューラルネットワークのパッケージでは、NSの重みのランダムな値による初期化が必須なので、MQLのヘルプ資料に従って行われたのではないかと思います。

つまり、このようなNSパッケージを使ってテスター内でMQLプログラムを使用する場合、おそらく1つのプロセッサコアで行われるでしょう。

srand()がないほうがかっこいい。

int OnInit()
   {
   return(INIT_SUCCEEDED);
   }
//+------------------------------------------------------------------+
void OnTick()
   {
   }
//+------------------------------------------------------------------+
double OnTester()
   {
      return(rand());
   }
//+------------------------------------------------------------------+
 
Igor Makanu:

これはドキュメントと矛盾しているhttps://www.mql5.com/ru/docs/math/mathrand

ソースコードは見たくないのですが、ニューラルネットワークのパッケージでは、NSの重みのランダムな値による初期化が必須なので、MQLのヘルプ資料に従って行われたのではないかと思います。

つまり、このようなNSパッケージを使ってテスター内でMQLプログラムを使用する場合、おそらく1つのプロセッサコアで行われるでしょう。

srand()抜きでも面白い。

Igor, では MathSrand(int(GetMicrosecondCount()%16384)) を試してみてください。

イメージがどう変わるかですね。