Conversando sobre a OLP no salão - página 4

 
Dennis Kirichenko:

Bem visto. Seria bom se os argumentos fossem apoiados por código e não apenas blá, blá, blá, blá.

Apoiando-o.

Aqui está minha classe 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

A macro CONVERT_OBJECT_WITH_CHECK também é definida no final, que para a versão DEBUG realiza uma verificação adicional de conversão de ponteiro com base no tipo de objeto

 
George Merts:

Apoiando-o.

Aqui está minha classe CMyObject:

A macro CONVERT_OBJECT_WITH_CHECK também é definida no final, que, para a versão DEBUG, realiza uma verificação adicional de conversão de ponteiro com base no tipo de objeto


É lindo. É claro, é uma questão de gosto. Mas, com base na sintaxe da MQL, eu a escreveria desta forma:

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:

É lindo. É claro, é uma questão de gosto. Mas, com base na sintaxe da MQL, eu a escreveria desta forma:

Sim, é isso mesmo.

Mas, este é meu senil "estilo de programação" (olá, Volchansky com seu recente fio condutor).

Tenho todas as enumerações - comece com E, e depois com a notação "hump" - nome. E os próprios tipos em enumeração começam com uma abreviação (até quatro letras) do tipo enumeração.

Portanto, como a enumeração é EMyObjectType, todos os valores começam com MOT_

 
Комбинатор:

Você é um idiota? )) Eu não disse uma palavra ruim sobre F#. Aprenda a ler e entender o que lhe é dito antes de publicar seus comentários estúpidos.

Se você comparar o OOP com FP, é mais sensato compará-lo com uma linguagem FP pura, ou seja, Haskel. F# já é mais ou menos assim, enquanto python e R não são de todo. É isso que eu quero dizer. Caso contrário, podemos chegar a um ponto em que C++ é também uma língua FP.

Você é um troll analfabeto. Para constar, todos os idiomas listados são funcionais de uma forma ou de outra. Vá e aprenda a área temática. A pergunta foi feita para entender qual quadro de referênciaAndrei pode estar praticando uma das línguas da PF, portanto a listagem foi muito geral.

 
George Merts:

O que isso quer dizer?

O que deveria estar no "objeto base" de acordo com você?

Pessoalmente tenho quase TODOS os objetos em todos os meus projetos - herdados da CMyObject: CObject público, (em meu objeto são adicionados mais dois campos - nome da classe e ID da instância), e descobri repetidamente que preciso muito da funcionalidade CObject::Comparar(). Algumas vezes os indicadores de lista também vieram a calhar.

CObject tem um objetivo - fornecer controle de tipo. E a gerencia de forma instável. Métodos como Next(), Prev(), etc., são para coleções muito especializadas. Eles não pertencem à CObject. O mesmo se aplica aos métodos de Salvar e Carregar. Também seria bom não ter Comparer nele, mas esta é a única solução sem interfaces.

Quanto ao método Type(), ele não fornece digitação rigorosa, pois retorna o número usual. Você pode ver no exemplo de seu próprio código. Você define um novo método GetType() que retorna o tipo como uma enumeração. Realmente não há outra maneira, eu mesmo faço isso. É por isso que o CObject padrão tem que ser anexado a ele, e é incorreto.

 

Vamos continuar em CObject::Comparar().

Tenho esse objeto CFactoryBalanceResultSeries - é uma série com resultados de equilíbrio com referência ao objeto de fábrica do Expert Advisor. Na verdade, é uma curva de equilíbrio na história com referência ao Expert Advisor que a negociou.

Portanto, tenho um roteiro onde comparo essas mesmas séries de equilíbrio.

Desde que haja apenas duas séries, é fácil compará-las. Mas quando há dezenas delas - não se pode comparar a olho nu, é preciso uma comparação mais formal.

E só para automatizar este processo - eu tive que escrever uma função que classificasse estas mesmas séries. E aqui foi útil, porque a classe CFactoryBalanceResultSeries é uma herdeira da CObject com sua função de comparação. Se anularmos esta função, temos uma possibilidade pronta de classificar as séries.

É assim que esta função se parece no meu 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);
};

Ou seja, dependendo do tipo de classificação - selecionamos a função de comparação necessária, que é usada na função de classificação geral.

Por exemplo, se quisermos ordenar a série de saldos pela parte do último sorteio a partir do máximo, serão utilizadas as seguintes funções:

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:

Vou continuar com CObject::Comparar().

Do recente

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:



Não é muito bonito, imho.

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));

Você poderia usar um ponteiro para uma função.

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:

Sim, isso mesmo.

Mas, esse é meu "estilo senil de programação" (olá, Wolchansky com seu recente fio condutor).

Tenho todas as enumerações - comece com E, e depois com a notação "hump" - o nome. E os próprios tipos em enumeração começam com uma abreviação (até quatro letras) do tipo enumeração.

Correspondentemente, desde a enumeração do EMyObjectType - todos os valores começam com MOT_


Sim, eu tenho a mesma enumeração.

ZS: Acabei de chegar ao computador. Como era de se esperar, este fio desceu rapidamente para o lixo). Vou tentar terminar a história sobre funções virtuais mais tarde. Devemos chamar este fórum de Blá Blá Blá Blá Blá).

 

Li os diferentes interesses de cada um... Estou no processo de redesenhar uma classe para montar e gerenciar uma grade virtual, preciso dela.