mql5におけるOOP、テンプレート、マクロ、微妙な使い分け - ページ 10 1...34567891011121314151617...28 新しいコメント Ilya Malev 2019.01.25 20:41 #91 Alexey Navoykov:結局、Interface<CBase>でも、Interface<C<B<A<CBase>>でも、何種類ものバリエーションがあり、CBaseをすべてのバリエーションに順次キャストしなければならず、それは非現実的である。 クラスオブジェクト 自体にインターフェースの情報を格納し、既存のインターフェースパッドに加えて、我々のパッドの上にラッパーとして機能する独立したインターフェースクラスを作ることを実装しようと思っていたのを覚えています。でも、そんなことは必要ない、余計なお世話だという結論に達したんです。実際のところ、ベースクラスをどのインターフェイスにキャストする必要があるのか見たことがありません。 唯一の選択肢は、デバッグのためにクラスがこのインターフェイスをサポートしているかどうかを調べることですが、そのためにキャストをする必要はありません。私見では、インターフェイスに格納するべきだと思います。Interface<T,CBase>::GetComparer().Compare(CBase &a, T& b); 私は例としてそこにいくつかのコードをスケッチしましたが、私はあまり多くの文字でフォーラムを混乱させたくないので、本当にそうします。 Artyom Trishkin 2019.01.25 20:43 #92 Ilya Malev:私見では、インターフェースはインターフェース自体に格納されるべきです。Interface<T,CBase>::GetComparer().Compare(CBase &a, T& b); 私は例としてそこにいくつかのコードをスケッチしましたが、私はあまり多くの文字でフォーラムを混乱させたくないので、本当にそうします。どうぞ、投稿してください。とにかく、ゴミではなく、議論の対象なのです。しかし、議論がここに移されたそのスレッドでは、不適切でしょう。 Ilya Malev 2019.01.25 20:44 #93 ok) //+------------------------------------------------------------------+ //| Comparer demo | //| Copyright 2012, CompanyName | //| http://www.companyname.net | //+------------------------------------------------------------------+ #property strict #define throw(M) {int a=0,b=1; printf("%s: %s",__FUNCSIG__,M); Print(b%a); } #define msg_pure "Method not implemented!" #define msg_compare "Types are uncomparable!" template<typename T,typename CBase> class IComparer; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ class Number { public: virtual int CompareTo(Number *par) { throw(msg_pure); return 0; } int operator==(Number*par) { return CompareTo(par); } template<typename T> T *operator[](T*) { return dynamic_cast<T*>(&this); } virtual string ToStr() { return StringFormat("Type %s, object %i (%i)",typename(this),&this,CheckPointer(&this)); } }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ class Int: public Number { private: int i; public: int Get() { return i; } Int*Set(int p) { i=p; return &this; } virtual int CompareTo(Number*par) { Int*v1=dynamic_cast<Int*>(par); if(v1) { return IComparer<Int,Int>::GetComparer()[ IComparer<Int,Int>::GetComparer() ].Compare( &this,v1 ); } Double*v2=dynamic_cast<Double*>(par); if(v2) { return IComparer<Double,Int>::GetComparer()[ IComparer<Double,Int>::GetComparer() ].Compare( &this,v2 ); } throw(msg_compare); return 0; } Int*operator=( int p ) { return Set( p ); } virtual string ToStr() { return IntegerToString(i); } }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ class Double: public Number { private: double f; public: double Get() { return f; } Double*Set(double p) { f=p; return &this; } virtual int CompareTo(Number*par) { Double*v1=dynamic_cast<Double*>(par); if(v1) { return IComparer<Double,Double>::GetComparer()[ IComparer<Double,Double>::GetComparer() ].Compare( &this,v1 ); } Int*v2=dynamic_cast<Int*>(par); if(v2) { return IComparer<Int,Double>::GetComparer()[ IComparer<Int,Double>::GetComparer() ].Compare( &this,v2 ); } throw(msg_compare); return 0; } Double*operator=(double p) { return Set(p); } virtual string ToStr() { return DoubleToString(f,_Digits); } }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ template<typename T,typename CBase> class IComparer: public CBase { private: static IComparer *comparer; public: IComparer() { if(!comparer) { comparer=&this; } } virtual int Compare(CBase &op1,T &op2) { throw(msg_pure); return 0; } static IComparer *GetComparer() { return comparer ? comparer : new IComparer; } static string ToStr(int cmp) { return(!cmp?"equal":(cmp==-1?"lesser than":(cmp==1?"greater than":"undefined"))); } }; template<typename T,typename CBase> IComparer *IComparer::comparer=NULL; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ class CmpIntToInt: public IComparer<Int,Int> { virtual int Compare(Int &op1,Int &op2) { return(op1.Get()>op2.Get())-(op1.Get()<op2.Get()); } } citi; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ class CmpIntToDouble: public IComparer<Int,Double> { virtual int Compare(Double &op1,Int &op2) { return int(op1.Get()-op2.Get()>DBL_EPSILON)-int(op2.Get()-op1.Get()>DBL_EPSILON); } } citd; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ class CmpDoubleToInt: public IComparer<Double,Int> { virtual int Compare(Int &op1,Double &op2) { return int(op1.Get()-op2.Get()>DBL_EPSILON)-int(op2.Get()-op1.Get()>DBL_EPSILON); } } cdti; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ class CmpDoubleToDouble: public IComparer<Double,Double> { virtual int Compare(Double &op1,Double &op2) { return int(op1.Get()-op2.Get()>DBL_EPSILON)-int(op2.Get()-op1.Get()>DBL_EPSILON); } } cdtd; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void OnStart() { srand(GetTickCount()); Number *n[10]; for(int i=0;i<10;i++) { if(rand()%2==0) n[i]=new Int=rand(); else n[i]=new Double=rand()*rand()/(1.0*rand()); } for(int i=0;i<10;i++) { int a=rand()%10,b=rand()%10; printf("%s is %s %s",n[a].ToStr(),IComparer<Int,Int>::ToStr(*n[a]==n[b]),n[b].ToStr()); } for(int i=0;i<10;i++) { delete n[i]; } } //+------------------------------------------------------------------+ Alexey Navoykov 2019.01.25 21:20 #94 Ilya Malev:ok) IComparer::Compare(CBase &op1, T &op2) メソッドは、両方の引数が T であるべきなのに、なぜ存在するのでしょう? Ilya Malev 2019.01.25 21:22 #95 Alexey Navoykov:また、IComparer::Compare(CBase &op1, T &op2) メソッドは、両引数がTでなければならないのに、なぜ存在するのでしょうか?同じ種類のものしか比較できないのでしょうか?私の想定では、そうではない。T==CBase とすると、両引数Tが存在することになる ) Alexey Navoykov 2019.01.25 21:27 #96 なるほど、それなら、IComparerクラスはIComparer<T1,T2,CBase>のようになるはずです。 したがって、そのメソッドもそうなります。 virtual Compare(T1 &op1, T2 &op2) = 0; そして、クラスを継承するときには、まさにこのメソッドをオーバーロードすることになり、すべてがうまくいくことになります。 Ilya Malev 2019.01.25 21:28 #97 Alexey Navoykov:なるほど、それならIComparerクラスはIComparer<T1,T2,CBase>のようなものでいいんですね。 そして、クラスを継承するときに、このメソッドをオーバーロードすれば、すべてがうまくいくのです。そして、このCBaseの意味するところは?また、なぜ1つの型から正確に2つの値を比較しなければならないのでしょうか? Ilya Malev 2019.01.25 21:31 #98 C#と全く同じにすることを目標にしているわけではなく、また、C#でどのように行われているのかを詳しく理解しているわけではありません。しかし、resetとnextの2つの関数のIEnumeratorは一見すると非常に不便で、私は絶対に同じフォームでコピーしない ) TheXpert 2019.01.25 21:34 #99 比較のためにダイナミックなキャストを使うなんて、どうかしてるぜ? 純粋な仮想関数は、次のように記述されます -virtual int CompareTo(Number *par) = 0 ; というのは、呪われるのはコンパイラであり、自分で書いた例外サロゲートではありません。 Ilya Malev 2019.01.25 21:36 #100 TheXpert:純粋な仮想関数は、次のように記述されます -virtual int CompareTo(Number *par) = 0; の場合、自分で書いた例外サロゲートの代わりにコンパイラが呪われることになります。私は常に基本型クラス(この例ではNumber)を操作しているので、コンパイラが悪態をつく必要はない。コンパイラに悪口を言われると、コードが全く動かなくなる 1...34567891011121314151617...28 新しいコメント 取引の機会を逃しています。 無料取引アプリ 8千を超えるシグナルをコピー 金融ニュースで金融マーケットを探索 新規登録 ログイン スペースを含まないラテン文字 このメールにパスワードが送信されます エラーが発生しました Googleでログイン WebサイトポリシーおよびMQL5.COM利用規約に同意します。 新規登録 MQL5.com WebサイトへのログインにCookieの使用を許可します。 ログインするには、ブラウザで必要な設定を有効にしてください。 ログイン/パスワードをお忘れですか? Googleでログイン
結局、Interface<CBase>でも、Interface<C<B<A<CBase>>でも、何種類ものバリエーションがあり、CBaseをすべてのバリエーションに順次キャストしなければならず、それは非現実的である。
クラスオブジェクト 自体にインターフェースの情報を格納し、既存のインターフェースパッドに加えて、我々のパッドの上にラッパーとして機能する独立したインターフェースクラスを作ることを実装しようと思っていたのを覚えています。でも、そんなことは必要ない、余計なお世話だという結論に達したんです。実際のところ、ベースクラスをどのインターフェイスにキャストする必要があるのか見たことがありません。 唯一の選択肢は、デバッグのためにクラスがこのインターフェイスをサポートしているかどうかを調べることですが、そのためにキャストをする必要はありません。
私見では、インターフェイスに格納するべきだと思います。Interface<T,CBase>::GetComparer().Compare(CBase &a, T& b); 私は例としてそこにいくつかのコードをスケッチしましたが、私はあまり多くの文字でフォーラムを混乱させたくないので、本当にそうします。
私見では、インターフェースはインターフェース自体に格納されるべきです。Interface<T,CBase>::GetComparer().Compare(CBase &a, T& b); 私は例としてそこにいくつかのコードをスケッチしましたが、私はあまり多くの文字でフォーラムを混乱させたくないので、本当にそうします。
どうぞ、投稿してください。とにかく、ゴミではなく、議論の対象なのです。しかし、議論がここに移されたそのスレッドでは、不適切でしょう。
ok)
ok)
IComparer::Compare(CBase &op1, T &op2) メソッドは、両方の引数が T であるべきなのに、なぜ存在するのでしょう?
また、IComparer::Compare(CBase &op1, T &op2) メソッドは、両引数がTでなければならないのに、なぜ存在するのでしょうか?
同じ種類のものしか比較できないのでしょうか?私の想定では、そうではない。T==CBase とすると、両引数Tが存在することになる )
なるほど、それなら、IComparerクラスはIComparer<T1,T2,CBase>のようになるはずです。 したがって、そのメソッドもそうなります。
そして、クラスを継承するときには、まさにこのメソッドをオーバーロードすることになり、すべてがうまくいくことになります。なるほど、それならIComparerクラスはIComparer<T1,T2,CBase>のようなものでいいんですね。
そして、クラスを継承するときに、このメソッドをオーバーロードすれば、すべてがうまくいくのです。そして、このCBaseの意味するところは?また、なぜ1つの型から正確に2つの値を比較しなければならないのでしょうか?
比較のためにダイナミックなキャストを使うなんて、どうかしてるぜ?
純粋な仮想関数は、次のように記述されます -virtual int CompareTo(Number *par) = 0 ;
というのは、呪われるのはコンパイラであり、自分で書いた例外サロゲートではありません。
純粋な仮想関数は、次のように記述されます -virtual int CompareTo(Number *par) = 0;
の場合、自分で書いた例外サロゲートの代わりにコンパイラが呪われることになります。
私は常に基本型クラス(この例ではNumber)を操作しているので、コンパイラが悪態をつく必要はない。コンパイラに悪口を言われると、コードが全く動かなくなる