Hablando de la OLP en el salón - página 4

 
Dennis Kirichenko:

Buen punto. Estaría bien que los argumentos estuvieran respaldados por el código en lugar de limitarse al bla, bla, bla.

Respaldándolo.

Aquí está mi clase CMyObject:

#include <Object.mqh>

// Перечисление, в котором должны указываться все объекты, которые могут быть пронаследованны от моего объекта
enum EMyObjectTypes
{
   MOT_BASE_OBJECT                              =  0001,          // Просто CObject - фактически, никогда не должен использоваться.
   MOT_STRUCT_WRAPPER                           =  0002,          // Неинициализированный CStructWrapper
   MOT_PRICE_POINT                              =  0003,          // Класс CPricePoint   
   MOT_PRICEIDX_POINT                           =  0004,          // Класс CPriceIdxPoint  
   MOT_WPRICEIDX_POINT                          =  0005,          // Класс CWPriceIdxPoint  
   MOT_WAVE_TRIANGLE_DATA                       =  0006,          // Класс CWaveTriangleData
   MOT_WAVE_TRIANGLE                            =  0007,          // Класс CWaveTriangle
   MOT_TRADERESULT_I                            =  0008,          // Класс CTradeResultI
   MOT_TRADERESULT                              =  0009,          // Класс CTradeResult

   // Тут еще куча типов объектов - для каждого класса, свой ID
           
   MOT_UNKNOWN                                  = -0001           // Неинициализированный объект.
};

/*

Класс СMyObject - потомок от СObject, несет функциональность именования.

*/

class CMyObject: public CObject
{
protected:
   EMyObjectTypes m_motType;
   int            m_iUDCreationValue;  // Значение, определяемое пользователем при создании объекта. Предназначено для идентификации отдельных экземпляров объекта.  
   
   
   void SetMyObjectType(EMyObjectTypes motType) { m_motType = motType; };  

   // Функции вывода на печать параметров. 
   void _PrintStringParameter(string strParameterName,string strParameterValue) { Print("Object ID: " + IntegerToString(GetType()) + "; " + strParameterName + " = " + strParameterValue + "; String."); };
   void _PrintDoubleParameter(string strParameterName,double dParameterValue,int iDigits = 8) { Print("Object ID: " + IntegerToString(GetType()) + "; " + strParameterName + " = " + DoubleToString(dParameterValue,iDigits) + "; Double"); };
   void _PrintIntegerParameter(string strParameterName,long lParameterValue) {  Print("Object ID: " + IntegerToString(GetType()) + "; " + strParameterName + " = " + IntegerToString(lParameterValue) + "; Integer"); };
   void _PrintBoolParameter(string strParameterName,bool bParameterValue) { if(bParameterValue) Print("Object ID: " + IntegerToString(GetType()) + "; " + strParameterName + " = True; Bool"); else Print("Object ID: " + IntegerToString(GetType()) + "; " + strParameterName + " = False; Bool"); };
   
public:
   CMyObject(int iUDCreationValue = WRONG_VALUE) { m_iUDCreationValue = iUDCreationValue;  m_motType = MOT_UNKNOWN;  };
   
   EMyObjectTypes GetType() const { return(m_motType);    };
   bool CheckType(EMyObjectTypes motType) { return(m_motType == motType); }; 
   
   int GetUDCreationValue() { return(m_iUDCreationValue); };
   void SetUDCreationValue(int iValue) { m_iUDCreationValue = iValue; };
};

#ifdef  ASSERTION_CODE_ON

CMyObject* _PerformObjectConvertWithCheck(CMyObject* pmoObject,EMyObjectTypes motType)
{
   ASSERT_MYPOINTER(pmoObject);                    // проверим указатель
   ASSERT(pmoObject.CheckType(motType) == true);   // проверим внутренний ID типа объекта
   
   return(pmoObject);
};

#define  CONVERT_OBJECT_WITH_CHECK(objFrom,typeTo,checkType) ((typeTo*)_PerformObjectConvertWithCheck(objFrom,checkType))

#else // ASSERTION_CODE_ON

#define  CONVERT_OBJECT_WITH_CHECK(objFrom,typeTo,checkType) ((typeTo*)objFrom)

#endif // ASSERTION_CODE_ON

También se define al final la macro CONVERT_OBJECT_WITH_CHECK, que para la versión DEBUG realiza una comprobación adicional de la conversión del puntero en función del tipo de objeto

 
George Merts:

Respaldándolo.

Aquí está mi clase CMyObject:

También se define al final la macro CONVERT_OBJECT_WITH_CHECK, que, para la versión DEBUG, realiza una comprobación adicional de la conversión del puntero en función del tipo de objeto


Es precioso. Por supuesto, es cuestión de gustos. Pero, basándome en la sintaxis de MQL, lo escribiría así:

enum ENUM_OBJECT_TYPES
{
   OBJECT_TYPES_BASE_OBJECT                              =  0001,          // Просто CObject - фактически, никогда не должен использоваться.
   OBJECT_TYPES_STRUCT_WRAPPER                           =  0002,          // Неинициализированный CStructWrapper
   OBJECT_TYPES_PRICE_POINT                              =  0003,          // Класс CPricePoint   
   OBJECT_TYPES_PRICEIDX_POINT                           =  0004,          // Класс CPriceIdxPoint  
   OBJECT_TYPES_WPRICEIDX_POINT                          =  0005,          // Класс CWPriceIdxPoint  
   OBJECT_TYPES_WAVE_TRIANGLE_DATA                       =  0006,          // Класс CWaveTriangleData
   OBJECT_TYPES_WAVE_TRIANGLE                            =  0007,          // Класс CWaveTriangle
   OBJECT_TYPES_TRADERESULT_I                            =  0008,          // Класс CTradeResultI
   OBJECT_TYPES_TRADERESULT                              =  0009,          // Класс CTradeResult

   // Тут еще куча типов объектов - для каждого класса, свой ID
           
   OBJECT_TYPES_UNKNOWN                                  = -0001           // Неинициализированный объект.
};
 
Dennis Kirichenko:

Es precioso. Por supuesto, es cuestión de gustos. Pero, basándome en la sintaxis de MQL, yo lo escribiría así:

Sí, así es.

Pero, este es mi senil "estilo de programación" (hola, Volchansky con su reciente hilo).

Tengo todas las enumeraciones - comienzan con E, y luego con la notación "joroba" - nombre. Y los propios tipos en enumeración comienzan con una abreviatura (hasta cuatro letras) de tipo de enumeración.

En consecuencia, dado que la enumeración es EMyObjectType, todos los valores comienzan por MOT_

 
Комбинатор:

¿Eres idiota? )) No he dicho ni una sola palabra mala sobre F#. Aprende a leer y a entender lo que se te dice antes de publicar tus estúpidos comentarios.

Si se compara la POO con la FP, es más sensato compararla con un lenguaje FP puro, es decir, Haskel. F# ya es más o menos, mientras que python y R no lo son en absoluto. Eso es lo que quiero decir. De lo contrario, podemos llegar a un punto en el que C++ sea también un lenguaje FP.

Eres un troll analfabeto. Para que conste, todas las lenguas enumeradas son funcionales de un modo u otro. Ve y aprende la materia. La pregunta se hizo para entender en qué marco de referenciaAndrei puede estar practicando una de las lenguas de FP, por lo que el listado era muy general.

 
George Merts:

¿Qué significa eso?

¿Qué debería haber en el "objeto base" según usted?

Personalmente tengo casi TODOS los objetos en todos mis proyectos - heredados de CMyObject: public CObject, (en mi objeto se añaden dos campos más - nombre de la clase e ID de la instancia), y repetidamente he encontrado que necesito mucho la funcionalidad de CObject::Compare(). Un par de veces los punteros de la lista también resultaron útiles.

CObject tiene un objetivo: proporcionar control de tipos. Y lo consigue de forma titubeante. Los métodos como Next(), Prev(), etc. son para colecciones muy especializadas. No pertenecen a CObject. Lo mismo ocurre con los métodos de guardar y cargar. Tampoco estaría mal que no hubiera Comparer, pero esta es la única solución sin interfaces.

En cuanto al método Type(), no proporciona una tipificación estricta, ya que devuelve el número habitual. Usted puede ver en el ejemplo de su propio código. Se define un nuevo método GetType() que devuelve el tipo como una enumeración. Realmente no hay otra manera, lo hago yo mismo. Por eso hay que añadirle el CObject estándar, que es incorrecto.

 

Continuemos con CObject::Compare().

Tengo dicho objeto CFactoryBalanceResultSeries - es una serie con resultados de balance con referencia al objeto de fábrica del Asesor Experto. En realidad es una curva de balance en la historia con referencia al Asesor Experto que ha operado.

Así que tengo un guión en el que comparo estas series tan equilibradas.

Mientras haya sólo dos series es fácil compararlas. Pero cuando hay docenas de ellos, no se puede comparar a ojo, se necesita una comparación más formal.

Y sólo para la automatización de este proceso - tuve que escribir una función que ordena estas mismas series. Y aquí fue útil, porque la clase CFactoryBalanceResultSeries es heredera de CObject con su función de comparación. Si anulamos esta función, tenemos una posibilidad de ordenar las series.

Así es como se ve esta función en mi caso:

int CFactoryBalanceResultSeries::Compare(const CObject *poNode,const int iMode) const
{
   CFactoryBalanceResultSeries* pfdsAnother = CONVERT_OBJECT_WITH_CHECK(poNode,CFactoryBalanceResultSeries,MOT_FACTORYBALANCERES_SERIES);
   
   switch(iMode)
      {
      case FSM_BY_PART_OF_MAX_DD_A:    return(_CompareByPartOfMaxDDWith(pfdsAnother,true));
      case FSM_BY_PART_OF_MAX_DD_D:    return(_CompareByPartOfMaxDDWith(pfdsAnother,false));

      case FSM_BY_PART_OF_MAX_SLQUEUE_A: return(_CompareByPartOfMaxSLQueueWith(pfdsAnother,true));
      case FSM_BY_PART_OF_MAX_SLQUEUE_D: return(_CompareByPartOfMaxSLQueueWith(pfdsAnother,false));

      case FSM_BY_LAST_PRCDATA_A:      return(_CompareByLastPrcdataWith(pfdsAnother,true));
      case FSM_BY_LAST_PRCDATA_D:      return(_CompareByLastPrcdataWith(pfdsAnother,false));
      case FSM_BY_LAST_MNYDATA_A:      return(_CompareByLastMnydataWith(pfdsAnother,true));
      case FSM_BY_LAST_MNYDATA_D:      return(_CompareByLastMnydataWith(pfdsAnother,false));
      case FSM_BY_LAST_MNYLOTDATA_A:   return(_CompareByLastMnylotdataWith(pfdsAnother,true));
      case FSM_BY_LAST_MNYLOTDATA_D:   return(_CompareByLastMnylotdataWith(pfdsAnother,false));
      
      case FSM_BY_PRCYEARRECOVERY_A:   return(_CompareByYearPrcrecoveryWith(pfdsAnother,true));
      case FSM_BY_PRCYEARRECOVERY_D:   return(_CompareByYearPrcrecoveryWith(pfdsAnother,false));
      case FSM_BY_MNYYEARRECOVERY_A:   return(_CompareByMnyYearRecoveryWith(pfdsAnother,true));
      case FSM_BY_MNYYEARRECOVERY_D:   return(_CompareByMnyYearRecoveryWith(pfdsAnother,false));
      case FSM_BY_MNYLOTYEARRECOVERY_A:return(_CompareByMnylotYearRecoveryWith(pfdsAnother,true));
      case FSM_BY_MNYLOTYEARRECOVERY_D:return(_CompareByMnylotYearRecoveryWith(pfdsAnother,false));
      
      case FSM_BY_PRCVAR_A:            return(_CompareByPrcVarWith(pfdsAnother,true));
      case FSM_BY_PRCVAR_D:            return(_CompareByPrcVarWith(pfdsAnother,false));
      case FSM_BY_MNYVAR_A:            return(_CompareByMnyVarWith(pfdsAnother,true));
      case FSM_BY_MNYVAR_D:            return(_CompareByMnyVarWith(pfdsAnother,false));
      case FSM_BY_MNYLOTVAR_A:         return(_CompareByMnylotVarWith(pfdsAnother,true));
      case FSM_BY_MNYLOTVAR_D:         return(_CompareByMnylotVarWith(pfdsAnother,false));
      
      case FSM_BY_PRC_GRAILRATIO_A:    return(_CompareByPrcGrailratioWith(pfdsAnother,true));
      case FSM_BY_PRC_GRAILRATIO_D:    return(_CompareByPrcGrailratioWith(pfdsAnother,false));

      case FSM_BY_MAGIC_A:             return(_CompareByMagicWith(pfdsAnother,true));
      case FSM_BY_MAIGC_D:             return(_CompareByMagicWith(pfdsAnother,false));
      default:
         break;
      };
         
   return(NULL);
};

Es decir, dependiendo del tipo de ordenación - seleccionamos la función de comparación requerida, que se utiliza en la función de ordenación común.

Por ejemplo, si queremos ordenar la serie de saldos por la parte de la última detracción del máximo, se utilizarán las siguientes funciones:

int CFactoryBalanceResultSeries::_CompareDblData(double dDataFirst,double dDataSecond,bool bAccending) const
{
   if(dDataFirst > dDataSecond)
      {
      if(bAccending)
         return(1);
      else   
         return(-1);
      };
   
   if(dDataFirst < dDataSecond)
      {
      if(bAccending)
         return(-1);
      else   
         return(1);
      };
      
   return(NULL);         
};

int CFactoryBalanceResultSeries::_CompareByPartOfMaxDDWith(CFactoryBalanceResultSeries* pfdsAnother,bool bAccending) const
{
   if(Total()==0 || pfdsAnother.Total() == 0 || m_pepfFactory.GetControlParams().m_dMaxPriceDrawdown == 0)
      return(NULL);
   
   double dLocalPart = GetCurPriceDD() / m_pepfFactory.GetControlParams().m_dMaxPriceDrawdown;
   double dRemotePart = pfdsAnother.GetCurPriceDD() / pfdsAnother.GetFactory().GetControlParams().m_dMaxPriceDrawdown;
      
   return(_CompareDblData(dLocalPart,dRemotePart,bAccending));   
};
 
George Merts:

Continuaré con CObject::Compare().

De la reciente

CDouble & CDoubleVector
CDouble & CDoubleVector
  • votos: 4
  • 2018.01.09
  • nicholishen
  • www.mql5.com
A library for common rounding methods used in MQL development, primitive wrapper class for type (double), and vector for CDouble objects. MQL5 and MQL4 compatible! CDouble The CDouble class wraps a value of the primitive type double in an object. Additionally, this class provides several methods and static methods for rounding doubles and...
 
George Merts:



No es muy bonito, en mi opinión.

int CFactoryBalanceResultSeries::Compare(const CObject *poNode,const int iMode) const
{
   CFactoryBalanceResultSeries* pfdsAnother = CONVERT_OBJECT_WITH_CHECK(poNode,CFactoryBalanceResultSeries,MOT_FACTORYBALANCERES_SERIES);
   
   switch(iMode)
      {
      case FSM_BY_PART_OF_MAX_DD_A:    return(_CompareByPartOfMaxDDWith(pfdsAnother,true));
      case FSM_BY_PART_OF_MAX_DD_D:    return(_CompareByPartOfMaxDDWith(pfdsAnother,false));

      case FSM_BY_PART_OF_MAX_SLQUEUE_A: return(_CompareByPartOfMaxSLQueueWith(pfdsAnother,true));
      case FSM_BY_PART_OF_MAX_SLQUEUE_D: return(_CompareByPartOfMaxSLQueueWith(pfdsAnother,false));

Podrías utilizar un puntero a una función.

typedef int (*TCompare1)(int,bool); 
// ---
int CFactoryBalanceResultSeries::Compare(const CObject *poNode,const int iMode) const
{
   CFactoryBalanceResultSeries* pfdsAnother = CONVERT_OBJECT_WITH_CHECK(poNode,CFactoryBalanceResultSeries,MOT_FACTORYBALANCERES_SERIES);
   
   switch(iMode)
      {
      case FSM_BY_PART_OF_MAX_DD_A:    return(TCompare1(pfdsAnother,true));
      case FSM_BY_PART_OF_MAX_DD_D:    return(TCompare1(pfdsAnother,false));

      case FSM_BY_PART_OF_MAX_SLQUEUE_A: return(TCompare1(pfdsAnother,true));
      case FSM_BY_PART_OF_MAX_SLQUEUE_D: return(TCompare1(pfdsAnother,false));

.....
      }
}
 
George Merts:

Sí, así es.

Pero, ese es mi senil "estilo de programación" (hola, Wolchansky con su reciente hilo).

Conmigo, todas las enumeraciones - comienzan con E, y luego con la notación "joroba" - nombre. Y los propios tipos en enumeración comienzan con una abreviatura (hasta cuatro letras) de tipo de enumeración.

En consecuencia, desde la enumeración EMyObjectType - todos los valores comienzan por MOT_


Sí, tengo la misma enumeración.

ZS: Acabo de llegar al ordenador. Como era de esperar, este hilo descendió rápidamente a la basura). Intentaré terminar la historia de las funciones virtuales más tarde. Deberíamos llamar a este foro Blah Blah Blah).

 

He leído los diferentes intereses de cada uno... Estoy en proceso de rediseñar una clase para montar y gestionar una red virtual, lo necesito.