タイピングに関する質問 - ページ 4

 
Ilya Malev:

何が問題なのか、あまり明確にはなっていません。オブジェクトの初期化は、Init()のような別のメソッド、あるいは仮想メソッドに置くことはできないのでしょうか?

はい、もちろんです。class.get_int()/class.get_double()/class.get_string()/... ができませんでした。?)).スタイル、習慣...

 
pavlick_:

もちろん、できますよ。class.get_int()/class.get_double()/class.get_string()/ ができませんでした。?)).スタイル、習慣...

できるのですが、double d, var[]; があるところで d=var[x].get_double と書かずに、d=var[x].get_double と書いてみましょう。マゾヒズムを発揮するならば、集団でやるべきだ =))

 
Ilya Malev:

つまり、メソッド呼び出しのコンテキストを定義し、そのコンテキストで期待される戻り値の型に応じて、必要なコードを呼び出すことができるようにすることです。

これは明らかにC++の標準ではなく、一般的にC++の良いところ(MQLの開発者が基礎として取り入れた)は、プログラマーが明示的に扱えないものはすべてC++でポインターを操作して、typedef 型に書かなければならないということです

ポインタは単なるメモリアドレスへのポインタであり、常にパラメータとして渡すことができ、関数の結果として得ることができます。ポインタを再参照するとメモリバイトの物理値が得られ、ポインタを新しい型に変換すると多くのメモリバイトが得られます )))

MQLでは、ポインターはなぜか言いにくいのですが、あります。開発者は、データ保護を優先しているので、サンドボックスからの脱出につながるような工夫はすべて排除していると言っています



についてですが、残念ながら私はテンプレート( template )を使った作業はほとんどやったことがないのですが、できるのではないかと思っています。

1. 必要な型を結果として返し、その型をパラメータとして受け取るオーバーロードされた関数をいくつか書く、つまり次のようにする。

//+------------------------------------------------------------------+
int f(const int x)
  {
   return((int)1);
  };
//+------------------------------------------------------------------+
double f(const double x)
  {
   return((double)2);
  }
//+------------------------------------------------------------------+
string f(const string x)
  {
   return((string)3);
  }
//+------------------------------------------------------------------+
void OnStart()
  { 
   int    a=0;
   double b=0;
   string c="0";
   a = f(a);
   b = f(b);
   c = f(c);
   Print("a = ",a);
   Print("b = ",b);
   Print("c = ",c);
}

2. f() 関数をテンプレートでラップして、パラメータ x を隠す必要があります - テンプレートでそうできる場合、呼び出しは a=f() になります - 視覚的にすべてがうまくいき、タイプするようになります

 
Igor Makanu:

明らかにC++の標準ではありません

私は長い間「純粋な」C++で書いたことはありませんが、ウェブ上にはこのようなコード例がたくさんあります。

class A
{
public:
    operator int()const;
};

A::operator int()const
{
    return 0;
}
 
Ilya Malev:

私はあなたが間違っていると思います。私は長い間「純粋な」C++で書いていませんが、ウェブにはこのようなコード例がたくさんあります。

しかし、それが複雑な型 であった場合はどうでしょうか?- 構造体なのか配列なのか? C++では、この問題を解決するために、型のポインタを使用しました。コンパイラはメモリアドレスを返し、ポインタを再参照することでデータが正しく処理されることを確認します。

 
Igor Makanu:

この例では正しく動作しますが、複雑な型の 場合はどうでしょうか?- C++では、これはその型へのポインタで解決され、コンパイラはメモリアドレスを返し、ポインタの再参照はデータの正しい取り扱いを提供しました。

このような例は、残念ながら、mqlでは正しく動作しないでしょう。

複雑な型、構造体、配列は必要なものをオーバーロードすることができ、型変換のオーバーロードは必要ない......。

 
Ilya Malev:

mqlでは、このような例は残念ながら正しく動作しません。

そうそう、今見たんだけど、型変換をオーバーロードしたいんだね、MQLのヘルプにはオーバーロードが許可されているとはっきり書いてあるし、単項演算はそれぞれ単項と二項としてしかオーバーロードできない、僕は行列を扱っていて^をオーバーロードしようとしたけどうまくいかない、仕方なく!

  • бинарные +,-,/,*,%,<<,>>,==,!=,<,>,<=,>=,=,+=,-=,/=,*=,%=,&=,|=,^=,<<=,>>=,&&,||,&,|,^;
  • 単項 +,-,++,--,~;
  • 代入演算子=。
  • インデックス演算子[]です。


私の例をもう一度見てみましたが、コンパイラは私の例をテンプレートで ラップすることを許可しません。 私は((1/x))を返すことが でき、パラメータxとして文字列を与えることができます。通常、すべてのCコンパイラはコンパイル時に型の一致をチェックし、MQLはあいまいなソリューションをテンプレートでラップすることは許可していません。

MQLでは、オーバーロードされた関数を すべて記述することで、正しく解決することができます。そうすれば、渡される変数や返される変数、オーバーロードされた関数はすべて、コンパイル時にチェック されます。

 
Igor Makanu:

MQLのヘルプによると、オーバーロードは許可されており、単項演算は単項と二項のそれぞれとしてのみオーバーロードされます。

99%言えることは、^がオーバーロードできないような状況は存在せず、一方、!また、オーバーロードの能力は演算子の種類に依存しません。何か勘違いしているのでは?ただ、この例をここに掲載しますが、すでに忘れて諦めている人はもちろんダメです)。

演算子の型に関する制限は、ポインタに適用される論理演算子 ==, !=, != のオーバーロードの禁止(any_type *)のみです。これらを正しくオーバーロードするためには、オートオブジェクトか構造体を扱う必要があります。ただ、ここ数ヶ月は、この手のもので犬をたくさん食べているので、自信を持って話せます :)

 
Ilya Malev:

99%言えるのは、^はオーバーロードしないが、! はオーバーロードする、という状況はないということです。また、オーバーロードの能力は、オペレーターの種類に依存しません。何か勘違いしているのでは?ただ、この例をここに掲載しますが、すでに忘れてしまっている人はやめたほうがいいでしょう)。

演算子の型に関する制限は、ポインタに適用される論理演算子 ==, !=, != のオーバーロードの禁止(any_type *)のみです。これらを正しくオーバーロードするためには、オートオブジェクトか構造体を扱う必要があります。ここ数ヶ月は、この仕掛けをたくさん食べているので、自信をもって言えます :)

#include <Math\Alglib\linalg.mqh>
class Matrix
  {
public:
   CMatrixDouble     M;
   int               row;//m_strok;
   int               col;//n_stolb;
   void              Matrix(void)         {                             }
   void              Matrix(int m,int n)  { M.Resize(m,n); row=m;col=n; }
   //----      умножение матриц
   Matrix operator*(const Matrix &B){Matrix res(this.row,B.col);CAblas::RMatrixGemm(this.row,B.col,this.col,1.0,this.M,0,0,0,B.M,0,0,0,0,res.M,0,0);return(res);  }
   //----      транспонирование матрицы
   Matrix operator!(void){Matrix res(this.col,this.row);CAblas::RMatrixTranspose(this.row,this.col,this.M,0,0,res.M,0,0);return(res);                             }
   //----      нулевая матрица
   void              zeros(int r,int c) {this.M.Resize(r,c);this.row=r;this.col=c;for(int i=0;i<r;i++){for(int j=0;j<c;j++){this.M[i].Set(j,0.0);}}               }
   //----      вывод в журнал матрицы
   void MatrixPrint(string  separator="|",uint digits=3){string s,sep=" "+separator+" ";for(int i=0;i<row;i++){s=separator;for(int j=0;j<col;j++) s+=DoubleToString(M[i][j],digits)+sep;Print(s);Sleep(123);}}
private:
   void              Matrix(const Matrix &R) { this=R;                                                                                                            }
  };

古典的な」行列処理では、行列の転置に ^ 演算子を使用する必要があります。これは、Matlab から SSA メソッドを移植したもので、CMatrixDouble に基づいて行列の乗算、代入、転置を最も単純化したものです。は、格納する行列のサイズ(行と列の数)を知らない。

 
追伸:ああ、つまり二項演算子を単項演算子としてオーバーロードしたい場合(2arを1arとして)、もちろんそうはいきませんね。唯一の例外は[]です。