Questions sur la POO (programmation orientée objet) - page 5

 
VOLDEMAR:

J'ai maintenant redessiné ma 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);
  }
Et ajouté l'héritage ... ( Je pense que je peux me tromper ) de la classe vr_MarketInfo

La classe vr_MarketInfo renvoie des informations sur le point, les chiffres du symbole et vérifie que le lot ne contient pas d'erreurs, et bien d'autres choses dont j'ai besoin pour mon travail, notamment pour tenir un journal dans Excel et sur un graphique.

Lorsqu'on utilise une méthode comme ci-dessus, une liste est donnée lorsqu'on travaille dans Primer.Primer.Primer()

Je voudrais faire quelque chose de plus abrégé...

Où est l'héritage ? Quel est l'intérêt du pointeur ?

 
Zhunko:

Où est l'héritage ? Quel est l'intérêt du pointeur ?


Rédigez un manuel sur MQL4+. Coopérez, connaisseurs, et écrivez-le. 50 dollars :)
 
En fait, le manuel et la documentation ne sont pas très précis quant à l'utilisation des pointeurs ou de l'opérateur new. Nous pouvons soit deviner, soit attendre que le temps passe. Ou quand quelqu'un dit accidentellement quelque chose quelque part. Je suis choqué par la façon dont les choses fonctionnent. Il est également intéressant de noter qu'à l'exception de moi et du topicstarter VLadimir, personne ne semble avoir besoin de quoi que ce soit. Bien que je continue à croire que de nombreuses personnes ne comprennent pas ce sujet. Et c'est pourquoi ils n'entrent pas dans ces questions...
 
tara:

Rédigez un manuel sur MQL4+. Coopérez, connaisseurs, et écrivez-le. 50 dollars :)

Tout a été écrit il y a longtemps.

MQL4 == C++ avec de légères limitations.

 
hoz:
En fait, ni le manuel, ni la documentation ne donnent de précisions sur la façon d'utiliser les pointeurs ou le nouvel opérateur. Nous pouvons soit deviner, soit attendre que le temps passe. Ou quand quelqu'un dit accidentellement quelque chose quelque part. Je suis choqué de voir comment cela se passe. Il est également intéressant de noter qu'à l'exception de moi et du topicstarter VLadimir, personne ne semble avoir besoin de quoi que ce soit. Bien que je continue à croire que de nombreuses personnes ne comprennent pas ce sujet. Et c'est pourquoi ils ne se mêlent pas de ces questions...


De quels éléments spécifiques avez-vous besoin ? Un principe s'applique partout : faire les choses aussi simplement que possible. N'entrez pas dans le vif du sujet juste pour être dans le vif du sujet. Si un problème peut être résolu simplement, il doit être résolu simplement.

Les pointeurs dynamiques sont nécessaires si votre programme doit travailler dynamiquement avec des objets : création, suppression pendant l'exécution du programme. Si vous savez à l'avance quels objets et combien sont nécessaires dans le programme, vous n'avez pas besoin de pointeurs dynamiques. Mais à moins que vous n'ayez beaucoup d'objets, vous pouvez simplement les créer dans une boucle avec new.


 
VOLDEMAR:
Je trouve par exemple difficile d'apprendre la théorie, montrez-moi un exemple et décrivez comment les fonctions définissent le cercle, le carré, le trapèze ou le triangle.

L'un des articles dont le lien figure dans le premier message contient cet exemple.

Une classe de base avec une méthode virtuelle. Le descendant possède une méthode portant le même nom, qui est utilisée pour effectuer des calculs.

 
VOLDEMAR:
Pour ma part, je trouve qu'il est difficile d'apprendre la théorie, de me montrer un exemple et de décrire comment les fonctions définissent un cercle, un carré, un trapèze ou un triangle ?


Je laisse le trapèze et le triangle à mon propre travail :

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

Les pointeurs dynamiques sont nécessaires si le programme doit travailler dynamiquement avec des objets : les créer, les supprimer pendant le fonctionnement du programme. Si vous savez à l'avance quels objets et combien seront nécessaires dans le programme, vous n'avez pas besoin de pointeurs dynamiques. Mais à moins que vous n'ayez beaucoup d'objets, il est plus facile de les créer dans une boucle avec new.

Exactement ! Et même dans ce cas, vous pouvez vous passer des pointeurs.
 
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;
  }
//+------------------------------------------------------------------+


Votre cours est redondant à 90%. Seules deux fonctions effectuent le travail principal, ce sont les openorders et tip Pourquoi utiliser Sel, Buy SelStop, etc., alors qu'en fait elles appellent toutes Openorders ? De plus, le type d'ordre est passé en tant que int, donc il n'est pas protégé. Au lieu de int, vous devriez utiliser votre propre énumération ou le standard ENUM_ORDER_TYPE. Et en général, il vaut mieux ne jamais utiliser les nombres magiques "1", "2" etc., seulement des énumérations. Cela vous empêchera d'envoyer la valeur d'ordre gauche à la fonction. La fonction Openorders elle-même est trop importante. De toute évidence, il se compose de deux blocs, celui de la conclusion d'un accord et celui de la vérification des conditions. Chacun d'entre eux devrait être une fonction privée distincte.

C'est un bon début, mais il y a encore beaucoup à apprendre. La fonction de pointe serait mieux réécrite comme suit :

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


Quelles sont les spécificités nécessaires ? Le même principe s'applique partout : tout doit être fait aussi simplement que possible. Vous n'avez pas besoin d'aller dans le désert juste pour être dans le désert. Si un problème peut être résolu simplement, il doit être résolu simplement.

Les pointeurs dynamiques sont nécessaires si le programme doit travailler dynamiquement avec des objets : création, suppression pendant le fonctionnement du programme. Si vous savez à l'avance quels objets et combien seront nécessaires dans le programme, vous n'avez pas besoin de pointeurs dynamiques. Mais sauf quand il y a beaucoup d'objets, il est plus facile de les créer dans une boucle via new.

Les pointeurs sont indispensables pour les conversions d'objets complexes où l'identification dynamique du type est requise.