OOP, mql5의 템플릿 및 매크로, 미묘함 및 사용 기술 - 페이지 10

 
Alexey Navoykov :

예, 일반적인 경우에는 여전히 의미가 없습니다. 결국 상속 체인은 무엇이든 될 수 있습니다. 최소한 Interface<CBase>, 최소한 Interface<C<B<A<CBase>>>>, 셀 수 없이 많은 옵션이 있습니다. CBase를 가능한 모든 옵션으로 순차적으로 캐스팅해야 하는데 이는 비현실적입니다.

클래스 개체 자체에 인터페이스에 대한 정보 저장을 구현하려고 했던 것을 기억합니다. 그리고 기존 인터페이스 패드에 추가하여 우리 패드에서 래퍼로 작동할 독립적인 인터페이스 클래스를 만듭니다. 예, 그제서야 이것이 모두 불필요하고 불필요하다는 결론에 도달했습니다. 기본 클래스를 인터페이스로 캐스팅할 실질적인 필요성을 보지 못했습니다. 그것은 단지 일종의 비논리적입니다. 유일한 옵션은 클래스가 디버깅 목적으로 주어진 인터페이스를 지원하는지 확인하는 것입니다. 그러나 이렇게 하려면 캐스팅이 필요하지 않습니다.

제 생각에는 인터페이스 자체에 인터페이스를 저장해야 합니다. 인터페이스<T,CBase>::GetComparer().Compare(CBase &a, T& b); 예를 들어 거기에 코드를 스케치했지만 포럼에 여러 글자로 흩어져 있는 것을 원하지 않습니다.

 
Ilya Malev :

제 생각에는 인터페이스 자체에 인터페이스를 저장해야 합니다. 인터페이스<T,CBase>::GetComparer().Compare(CBase &a, T& b); 예를 들어 거기에 코드를 스케치했지만 포럼에 여러 글자로 흩어져 있는 것을 원하지 않습니다.

퍼뜨려라. 어쨌든 이것은 쓰레기가 아니라 토론의 주제입니다. 토론이 여기로 옮겨진 스레드에서 바로 여기 - 예, 부적절할 것입니다.

 

확인)

 //+------------------------------------------------------------------+
//|                                                    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 :

확인)

두 인수가 모두 T여야 하는 경우 IComparer::Compare( CBase &op1, T &op2) 메서드가 있는 이유

 
Alexey Navoykov :

두 인수가 모두 T여야 하는 경우 IComparer::Compare( CBase &op1, T &op2) 메서드가 있는 이유

같은 종류만 비교 가능한가요? 나는 아니라고 가정했다. T==CBase 를 수행하고 두 인수 모두 T )

 

아, 이해합니다. 그럼 당신은 모든 것을 잘못했습니다. 귀하의 경우 IComparer 클래스는 IComparer<T1,T2,CBase>와 같아야 합니다. 따라서 방법은 다음과 같습니다.

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

그리고 클래스를 상속할 때 이 특정 메서드를 오버로드하면 모든 것이 제자리에 있게 됩니다.
 
Alexey Navoykov :

아, 이해합니다. 그럼 당신은 모든 것을 잘못했습니다. 귀하의 경우 IComparer 클래스는 IComparer<T1,T2,CBase>와 같아야 합니다. 따라서 방법은 다음과 같습니다.

그리고 클래스를 상속할 때 이 특정 메서드를 오버로드하면 모든 것이 제자리에 있게 됩니다.

이 CBase의 요점은 무엇입니까? 그리고 같은 유형의 정확히 2개의 값을 비교해야 하는 이유는 무엇입니까?

 
C#처럼 정확히 하려는 목표가 없고, 거기에서 모든 것이 어떻게 수행되었는지 자세히 이해하지 못했습니다. 그러나 두 가지 기능의 동일한 IEnumerator가 재설정되고 다음이 매우 불편하므로 동일한 형식으로 복사하지 않을 것입니다)
 

비교를 위한 다이나믹 캐스트?? 당신 미쳤어?

순전히 가상 기능 은 다음과 같이 작성됩니다 - 가상 int CompareTo(숫자 *par) = 0;

자체 작성 예외 대리가 아닌 컴파일러가 맹세합니다.

 
TheXpert :

순전히 가상 기능 은 다음과 같이 작성됩니다 - 가상 int CompareTo(숫자 *par) = 0;

컴파일러는 스스로 작성한 예외 대리가 아닌 맹세합니다.

나는 기본 유형의 클래스(이 예에서는 Number)를 지속적으로 조작하기 때문에 컴파일러가 맹세할 필요가 없습니다. 컴파일러가 그에게 맹세하면 코드가 전혀 실행되지 않습니다.