Perguntas OOP (Object Oriented Programming) - página 5

 
VOLDEMAR:

Agora redesenhei minha classe

class vr_trade
  {
private:
   int               openorders(string sy,int typ,double lot,double price);
   string            tip(int typ);
   int               m_magic;
   int               m_slip;
public:
   int               Buy(string sy,double lot);
   int               Sel(string sy,double lot);
   int               BuyLimit(string sy,double lot,double price);
   int               SelLimit(string sy,double lot,double price);
   int               BuyStop(string sy,double lot,double price);
   int               SelStop(string sy,double lot,double price);
   void              MagSlip(int mag=-1,int slip=0);
   vr_MarketInfo    *Log;
                     vr_trade();
                    ~vr_trade();
  };
MqlTick st;
//+------------------------------------------------------------------+
vr_trade:: vr_trade()
  {
   Log=new vr_MarketInfo;
   MagSlip(-1,0);
  }
E acrescentou a herança ... ( suspeito que posso estar errado ) da classe vr_MarketInfo

A classe vr_MarketInfo retorna informações sobre Ponto, Dígitos para o símbolo e verifica o lote em busca de erros, e muitas outras coisas que eu preciso para o trabalho, incluindo manter um log em Excel e em um gráfico

Quando se usa um método como o acima é dada uma lista quando se trabalha em Primer.Primer.Primer()

Eu gostaria de fazer algo mais abreviado...

Onde está a herança? Qual é o objetivo do ponteiro?

 
Zhunko:

Onde está a herança? Qual é o objetivo do ponteiro?


Escreva um livro didático sobre a MQL4+. Cooperar, conhecedores e escrevê-lo. 50 dólares :)
 
Na verdade, o livro didático e a documentação não são muito específicos sobre o uso de ponteiros ou do novo operador. Podemos adivinhar ou esperar que o tempo passe. Ou quando alguém, acidentalmente, diz algo em algum lugar. Estou chocado com a forma como as coisas funcionam. Também é interessante que, exceto para mim e para o iniciante do tópico VLadimir, ninguém parece precisar de nada. Embora eu ainda acredite que muitas pessoas não entendam este tópico. E é por isso que eles não se metem em tais questões...
 
tara:

Escreva um livro didático sobre a MQL4+. Cooperar, conhecedores e escrevê-lo. 50 dólares :)

Tudo foi escrito há muito tempo.

MQL4 == C++ com ligeiras limitações.

 
hoz:
De fato, nem o manual, nem a documentação oferece nenhuma informação específica sobre como utilizar os indicadores, ou o novo operador. Podemos adivinhar ou esperar que o tempo passe. Ou quando alguém, acidentalmente, diz algo em algum lugar. Estou chocado como isso acontece. É também interessante que, exceto para mim e para o iniciante do tópico VLadimir, ninguém parece precisar de nada. Embora eu ainda acredite que muitas pessoas não entendam este tópico. E é por isso que eles não se envolvem em tais questões...


De que tipo de especificações você precisa? Um princípio se aplica em toda parte: manter as coisas o mais simples possível. Não entre na espessura das coisas só para estar na espessura das coisas. Se um problema pode ser resolvido de forma simples, ele deve ser resolvido de forma simples.

São necessários indicadores dinâmicos se seu programa precisar trabalhar dinamicamente com objetos: criar, apagar durante a execução do programa. Se você sabe com antecedência quais e quantos objetos são necessários no programa, você não precisa de indicadores dinâmicos. Mas, a menos que você tenha muitos objetos, você pode simplesmente criá-los em um loop com novos.


 
VOLDEMAR:
Eu, por exemplo, acho difícil aprender a teoria, mostrar-me um exemplo e descrever como as funções definem círculo, quadrado, trapézio ou triângulo.

Um dos artigos vinculados no primeiro post tem este exemplo.

Uma classe base com um método virtual. O descendente tem um método com o mesmo nome, que é usado para fazer cálculos.

 
VOLDEMAR:
Eu, por exemplo, acho difícil aprender a teoria, mostrar-me um exemplo e descrever como as funções definem um círculo, quadrado, trapezoidal ou triângulo ???


Deixo o trapézio e o triângulo para meu próprio trabalho:

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
class CShape
  {
  
public:
   virtual string Type()      { return(""); }
   virtual double Perimeter() { return(-1); }
   virtual double Square()    { return(-1); }
  };
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
class CCircle : public CShape
  {
   double         m_r;
  
public:
                  CCircle(double r):m_r(r) { }
   virtual string Type()      { return("circle");     }
   virtual double Perimeter() { return(2*M_PI*m_r);   }
   virtual double Square()    { return(M_PI*m_r*m_r); }
  };
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
class CRectangle : public CShape
  {
   double         m_a;   
   double         m_b;
   
public:
                  CRectangle(double a,double b):m_a(a),m_b(b) { }
   virtual string Type()      { return("rectangle");  }
   virtual double Perimeter() { return(m_a*2+m_b*2);  }
   virtual double Square()    { return(m_a*m_b);      }   
  };
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnStart()
  {
   CShape *shape[10];
//--- создаём объекты
   for(int n=0;n<10;n++)
     {
      if((MathRand()&1)==1)
         shape[n]=new CCircle(MathRand()%10+1);
      else
         shape[n]=new CRectangle(MathRand()%10+1,MathRand()%10+1);
     }
//--- выводим данные по объектам
   for(int n=0;n<10;n++)
      PrintFormat("%s p=%.3f s=%.3f",shape[n].Type(),shape[n].Perimeter(),shape[n].Square());
//--- удаляем объекты
   for(int n=0;n<10;n++)
      delete shape[n];
  }
//+------------------------------------------------------------------+
 
Integer:

Indicadores dinâmicos são necessários se o programa precisar trabalhar com objetos dinamicamente: criando, apagando-os durante a operação do programa. Se você sabe com antecedência quais e quantos objetos serão necessários no programa, você não precisa de indicadores dinâmicos. Mas, a menos que você tenha muitos objetos, é mais fácil criá-los em um loop com novos.

Exatamente! E mesmo nesse caso você pode fazer sem indicações.
 
VOLDEMAR:
#property strict
input int Slip=30;
input int Magic=0;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
class vr_trade
  {
private:
   int               openorders(string sy,int typ,double lot,double price);
   string            tip(int typ);
public:
   int               Buy(string sy,double lot);
   int               Sel(string sy,double lot);
   int               BuyLimit(string sy,double lot, double price);
   int               SelLimit(string sy,double lot, double price);
   int               BuyStop(string sy,double lot, double price);
   int               SelStop(string sy,double lot, double price);
                     vr_trade(){}
                    ~vr_trade(){}
  };
MqlTick st;
vr_trade trade;
//+------------------------------------------------------------------+
void OnTick()
  {
trade.Buy("EURUSD",0.01); // Пример открытия позиции возвращающей тиккет ордера.
  }
//+------------------------------------------------------------------+  
int vr_trade :: Buy(string sy,double lot)
{
return openorders(sy,0,lot);
}
//+------------------------------------------------------------------+  
int vr_trade :: Sel(string sy,double lot)
{
return openorders(sy,1,lot);
}
//+------------------------------------------------------------------+  
int vr_trade :: BuyLimit(string sy,double lot, double price)
{
return openorders(sy,2,lot,price);
}
//+------------------------------------------------------------------+  
int vr_trade :: SelLimit(string sy,double lot, double price)
{
return openorders(sy,3,lot,price);
}
//+------------------------------------------------------------------+  
int vr_trade :: BuyStop(string sy,double lot, double price)
{
return openorders(sy,4,lot,price);
}
//+------------------------------------------------------------------+  
int vr_trade :: SelStop(string sy,double lot, double price)
{
return openorders(sy,5,lot,price);
}
//+------------------------------------------------------------------+
int vr_trade :: openorders(string sy="",int typ=0,double lot=0,double price=0)
  {
   int tik=-2;
   double di=NormalizeDouble(500*_Point,_Digits);
   if(sy==""){sy=_Symbol;Print("Установлен символ текущего графика ",sy);}
   if(lot<MarketInfo(sy,MODE_MINLOT)){lot=MarketInfo(sy,MODE_MINLOT); Print("Советник скорректировал лот ",lot);}
   if(!SymbolInfoTick(sy,st))Print("Не удалось прогрузить цены для символа ",sy);
   if(price==0)//Даблы так лучше не сравнивать.
     {
      if(typ==0)price=st.ask;
      if(typ==1)price=st.bid;
      if(typ==2)price=st.ask-di;
      if(typ==3)price=st.bid+di;
      if(typ==4)price=st.ask+di;
      if(typ==5)price=st.bid-di;
     }
   if(IsTradeAllowed()==true)
     {
      RefreshRates();
      tik=OrderSend(sy,typ,lot,price,Slip,0,0,"",Magic,0,clrRed);
      if(tik>0)Print("Успешно открыт ордер Ticket ",tik," Typ ",tip(typ)," Symbol ",sy," Lot ",lot," Price ",price);
      else Print("Ошибка открытия ордера N",GetLastError());
     }
   else
      Print("Торговый поток занят");
   return tik;
  }
//+------------------------------------------------------------------+
string vr_trade :: tip(int typ ENUM_ORDER_TYPE type)
  {
   string txt="";
   switch(typ)
     {
      case 0: txt="BUY";        break;
      case 1: txt="SELL";       break;
      case 2: txt="BUY LIMIT";  break;
      case 3: txt="SELL LIMIT"; break;
      case 4: txt="BUY STOP";   break;
      case 5: txt="SELL STOP";  break;
      default : txt="Ошибка типа ордера";
     }
   return txt;
  }
//+------------------------------------------------------------------+


Sua classe é 90% redundante. Apenas duas funções realizam o trabalho principal, estas são ordens abertas e dica Por que você usa Sel, Comprar SelStop, etc., quando na verdade todas elas simplesmente chamam Openorders? Além disso, o tipo de pedido é passado como int, portanto não é protegido. Em vez de int é melhor usar ou sua própria enumeração ou o ENUM_ORDER_TYPE padrão. E em geral, é melhor nunca usar números mágicos "1", "2" etc., apenas enumerações. Isto impedirá que você envie o valor da ordem à esquerda para a função. A própria função Openorders é muito grande. Obviamente, ele consiste em dois blocos, o bloco de fazer um negócio e o bloco de verificar as condições. Cada um deles deve ser como uma função privada separada.

É um bom começo, mas ainda há muito a aprender. A função da ponta seria melhor reescrita da seguinte forma:

string vr_trade::tip(ENUM_ORDER_TYPE orderType)
{
   return EnumToString(orderType);
}
 
Integer:


Quais são as especificidades necessárias? O mesmo princípio se aplica em todos os lugares: tudo deve ser feito da maneira mais simples possível. Não é preciso ir para o deserto só para estar no deserto. Se um problema pode ser resolvido de forma simples, ele deve ser resolvido de forma simples.

Indicadores dinâmicos são necessários se o programa precisar trabalhar dinamicamente com objetos: criando, apagando durante a operação do programa. Se você sabe com antecedência quais e quantos objetos serão necessários no programa, você não precisa de indicadores dinâmicos. Mas, exceto quando há tantos objetos, é mais fácil criá-los em loop através de novos.

Os apontadores são indispensáveis para conversões de objetos complexos onde a identificação dinâmica do tipo é necessária.