OOP, Vorlagen und Makros in mql5, Feinheiten und Anwendungen - Seite 10

 
Alexey Navoykov:

Schließlich könnte die Vererbungskette alles sein, was man will: sogar Interface<CBase>, sogar Interface<C<B<A<CBase>>>>, es gibt tonnenweise Varianten. Wir müssten CBase sequentiell in alle möglichen Varianten casten, was unrealistisch ist.

Ich erinnere mich, dass ich vorhatte, die Speicherung von Informationen über Schnittstellen im Klassenobjekt selbst zu implementieren und zusätzlich zu den bestehenden Schnittstellen-Pads unabhängige Schnittstellenklassen zu erstellen, die als Wrapper über unser Pad funktionieren würden. Doch dann kam ich zu dem Schluss, dass all dies unnötig und überflüssig war. In der Praxis habe ich noch nie eine Notwendigkeit gesehen, eine Basisklasse auf eine Schnittstelle zu casten, es macht einfach keinen Sinn. Die einzige Möglichkeit ist, herauszufinden, ob die Klasse diese Schnittstelle zu Debugging-Zwecken unterstützt, aber dafür brauchen wir kein Casting.

Meiner Meinung nach sollten wir die Schnittstelle in der Schnittstelle speichern. Interface<T,CBase>::GetComparer().Compare(CBase &a, T& b); Ich habe dort etwas Code für ein Beispiel skizziert, aber ich möchte das Forum nicht mit zu vielen Buchstaben überfrachten.

 
Ilya Malev:

Meiner Meinung nach sollte die Schnittstelle in der Schnittstelle selbst gespeichert werden. Interface<T,CBase>::GetComparer().Compare(CBase &a, T& b); Ich habe dort etwas Code für ein Beispiel skizziert, aber ich möchte das Forum nicht mit zu vielen Buchstaben überfrachten.

Machen Sie weiter und veröffentlichen Sie es. Wie auch immer, es ist kein Unsinn, sondern ein Thema für Diskussionen. Aber in dem Thread, aus dem die Diskussion hierher verschoben wurde, wäre es unangebracht.

 

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

ok)

Warum gibt es die MethodeIComparer::Compare(CBase &op1, T &op2), wenn beide Argumente T sein sollten?

 
Alexey Navoykov:

Und warum gibt es die MethodeIComparer::Compare(CBase &op1, T &op2), wenn beide Argumente T sein müssen

Ist es nur möglich, die gleichen Typen zu vergleichen? Ich gehe davon aus, dass dies nicht der Fall ist. Machen Sie T==CBase und es werden beide Argumente T )

 

Ah, ich hab's, dann hast du es ganz falsch verstanden. Die Klasse IComparer sollte in deinem Fall wie IComparer<T1,T2,CBase> sein. Dementsprechend wird auch die Methode:

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

Und wenn Sie die Klasse erben, werden Sie genau diese Methode überladen, und alles wird sich fügen.
 
Alexey Navoykov:

Ah, ich sehe, Sie haben es ganz falsch dann. IComparer Klasse in Ihrem Fall sollte wie IComparer<T1,T2,CBase> sein:

Und wenn Sie eine Klasse erben, werden Sie diese Methode überladen, und alles wird sich fügen.

Und was ist die Bedeutung dieser CBase? Und warum müssen genau 2 Werte desselben Typs verglichen werden?

 
Ich habe nicht das Ziel, es genau wie in C# zu machen, außerdem habe ich nicht im Detail verstanden, wie es dort gemacht wird. Aber auf den ersten Blick ist der IEnumerator von zwei Funktionen reset und next sehr unpraktisch, ich würde ihn definitiv nicht in der gleichen Form kopieren )
 

dynamische Besetzung zum Vergleich? sind Sie verrückt geworden?

eine rein virtuelle Funktion wird wie folgt geschrieben -virtual int CompareTo(Number *par) = 0 ;

ist es der Compiler, der verflucht wird, und nicht das selbst geschriebene Ausnahmesurrogat.

 
TheXpert:

eine rein virtuelle Funktion ist wie folgt geschrieben -virtual int CompareTo(Number *par) = 0;

wird der Compiler anstelle des selbstgeschriebenen Ausnahme-Surrogats verflucht.

Ich brauche den Compiler nicht zu fluchen, weil ich ständig Basistypklassen (in diesem Beispiel Number) manipuliere. Wenn der Compiler darauf schimpft, läuft der Code gar nicht