OOP, mql5'te şablonlar ve makrolar, incelikler ve kullanım teknikleri - sayfa 10

 
Alexey Navoykov :

Evet ve genel durumda hala bir anlam ifade etmiyor. Sonuçta, miras zinciri herhangi bir şey olabilir: en azından Interface<CBase>, en azından Interface<C<B<A<CBase>>>>, sayısız seçenek var. Gerçekçi olmayan tüm olası seçeneklere sırayla CBase yayınlamanız gerekecek.

Arayüzler hakkındaki bilgilerin depolanmasını sınıf nesnesinin kendisinde uygulayacağımı hatırlıyorum. Ve mevcut arabirim pedlerine ek olarak, pedimizde sarmalayıcı olarak çalışacak bağımsız arabirim sınıfları yapın. Evet, ancak o zaman tüm bunların gereksiz ve gereksiz olduğu sonucuna vardım. Temel sınıfı herhangi bir arayüze dönüştürmek için herhangi bir pratik ihtiyaç görmedim. Bu sadece biraz mantıksız. Tek seçenek, sınıfın hata ayıklama amacıyla belirli bir arabirimi destekleyip desteklemediğini bulmaktır, ancak bu, bu şekilde yayınlamayı gerektirmez.

Bence arayüzü arayüzün kendisinde saklamanız gerekiyor. Arayüz<T,CBase>::GetComparer().Compare(CBase &a, T& b); Kodu bir örnek olarak orada çizdim, ancak bir şey forumu çok harfli olarak doldurmak istemiyor.

 
Ilya Malev :

Bence arayüzü arayüzün kendisinde saklamanız gerekiyor. Arayüz<T,CBase>::GetComparer().Compare(CBase &a, T& b); Kodu bir örnek olarak orada çizdim, ancak bir şey forumu çok harfli olarak doldurmak istemiyor.

Yay. Her durumda, bu çöp değil, bir tartışma konusudur. İşte tartışmanın buraya taşındığı başlıkta, tam orada - evet, uygunsuz olurdu.

 

TAMAM)

 //+------------------------------------------------------------------+
//|                                                    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];
     }
  }
//+------------------------------------------------------------------+
 
Ilya Malev :

TAMAM)

Her iki bağımsız değişkenin de T olması gerekiyorsa neden bir IComparer::Compare( CBase &op1, T &op2) yöntemi var?

 
Alexey Navoykov :

Her iki bağımsız değişkenin de T olması gerekiyorsa neden bir IComparer::Compare( CBase &op1, T &op2) yöntemi var?

Sadece aynı türleri karşılaştırmak mümkün müdür? hayır varsaydım. T==CBase yapın ve her iki argüman da T olacaktır)

 

Ah, anlıyorum, o zaman her şeyi yanlış yaptın. Sizin durumunuzdaki IComparer sınıfı, IComparer<T1,T2,CBase> gibi olmalıdır. Buna göre yöntem şu şekilde olacaktır:

virtual Compare(T1 &op1, T2 &op2) = 0 ;

Ve bir sınıfı miras alırken, bu belirli yöntemi aşırı yükleyeceksiniz, her şey yerine oturacak.
 
Alexey Navoykov :

Ah, anlıyorum, o zaman her şeyi yanlış yaptın. Sizin durumunuzdaki IComparer sınıfı, IComparer<T1,T2,CBase> gibi olmalıdır. Buna göre yöntem şu şekilde olacaktır:

Ve bir sınıfı miras alırken, bu belirli yöntemi aşırı yükleyeceksiniz, her şey yerine oturacak.

Bu CBase'in amacı nedir? Ve neden aynı türden tam olarak 2 değer karşılaştırılmalı?

 
Tam olarak C# daki gibi yapmak gibi bir amacım yok ayrıca orada her şeyin nasıl yapıldığını detaylı olarak anlamadım. Ancak hazırlıksız, iki işlevin aynı IEnumerator'ı sıfırlanır ve sonraki son derece elverişsizdir, kesinlikle aynı biçimde kopyalamazdım)
 

karşılaştırma için dinamik döküm? aklını mı kaçırdın?

tamamen sanal bir işlev şöyle yazılır - sanal int CompareTo(Sayı *par) = 0;

derleyici yemin edecek ve kendi kendine yazılmış bir istisna vekili değil.

 
TheXpert :

tamamen sanal bir işlev şöyle yazılır - sanal int CompareTo(Sayı *par) = 0;

derleyici yemin edecek ve kendi kendine yazılmış bir istisna vekili değil.

Derleyicinin küfretmesine ihtiyacım yok çünkü sürekli olarak temel türün sınıflarını değiştiriyorum (bu örnekte, Sayı). Derleyici ona yemin ederse, kod hiç çalıştırılmayacaktır.