Fragen zu OOP (Objektorientierte Programmierung) - Seite 5

 
VOLDEMAR:

Ich habe meinen Unterricht jetzt neu gestaltet

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);
  }
Und hinzu kommt das Erbe ... (ich vermute, ich könnte mich irren) aus der Klasse vr_MarketInfo

Die vr_MarketInfo-Klasse gibt Informationen über Point, Digits für das Symbolzurück und prüft das Lot auf Fehler und viele andere Dinge, die ich für die Arbeit benötige, einschließlich des Führens eines Protokolls in Excel und in einem Diagramm

Bei der Verwendung einer Methode wie der obigen wird bei der Arbeit in Primer.Primer.Primer() eine Liste angegeben

Ich würde gerne etwas kürzeres machen...

Wo ist das Erbe? Was ist der Sinn des Zeigers?

 
Zhunko:

Wo ist das Erbe? Was ist der Sinn des Zeigers?


Schreiben Sie ein Lehrbuch über MQL4+. Arbeitet zusammen, Kenner, und schreibt es. 50 Mäuse :)
 
In der Tat sind das Lehrbuch und die Dokumentation nicht sehr spezifisch, was die Verwendung von Zeigern oder des neuen Operators angeht. Wir können entweder raten oder warten, bis das Wetter vorbei ist. Oder wenn jemand aus Versehen irgendwo etwas sagt. Ich bin schockiert, wie die Dinge funktionieren. Es ist auch interessant, dass außer mir und dem Themenstarter VLadimir niemand etwas zu brauchen scheint. Ich glaube aber immer noch, dass viele Menschen dieses Thema nicht verstehen. Und deshalb gehen sie nicht auf solche Fragen ein...
 
tara:

Schreiben Sie ein Lehrbuch über MQL4+. Arbeitet zusammen, Kenner, und schreibt es. 50 Mäuse :)

Alles wurde schon vor langer Zeit geschrieben.

MQL4 == C++ mit leichten Einschränkungen.

 
hoz:
Weder im Handbuch noch in der Dokumentation finden sich nähere Angaben zur Verwendung von Zeigern oder des neuen Operators. Wir können entweder raten oder warten, bis das Wetter vorbei ist. Oder wenn jemand aus Versehen irgendwo etwas sagt. Ich bin schockiert, wie das passiert. Es ist auch interessant, dass außer mir und dem Themenstarter VLadimir niemand etwas zu brauchen scheint. Ich glaube aber immer noch, dass viele Menschen dieses Thema nicht verstehen. Und deshalb mischen sie sich nicht in solche Fragen ein...


Was brauchen Sie genau? Ein Grundsatz gilt überall: die Dinge so einfach wie möglich halten. Mischen Sie sich nicht ins Getümmel, nur um im Getümmel zu sein. Wenn ein Problem einfach gelöst werden kann, muss es auch einfach gelöst werden.

Dynamische Zeiger werden benötigt, wenn Ihr Programm dynamisch mit Objekten arbeiten muss : Erstellen, Löschen während der Ausführung des Programms. Wenn Sie im Voraus wissen, welche und wie viele Objekte im Programm benötigt werden, brauchen Sie keine dynamischen Zeiger. Aber wenn Sie nicht viele Objekte haben, können Sie sie einfach in einer Schleife mit new erstellen.


 
VOLDEMAR:
Ich zum Beispiel finde es schwer, die Theorie zu lernen. Zeigen Sie mir ein Beispiel und beschreiben Sie, wie Funktionen Kreis, Quadrat, Trapez oder Dreieck definieren.

In einem der im ersten Beitrag verlinkten Artikel findet sich dieses Beispiel.

Eine Basisklasse mit einer virtuellen Methode. Der Nachkomme hat eine Methode mit demselben Namen, die für Berechnungen verwendet wird.

 
VOLDEMAR:
Ich für meinen Teil finde es schwierig, die Theorie zu lernen, zeige mir ein Beispiel und beschreibe, wie Funktionen einen Kreis, ein Quadrat, ein Trapez oder ein Dreieck definieren?


Ich überlasse Trapez und Dreieck meiner eigenen Arbeit:

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

Dynamische Zeiger werden benötigt, wenn das Programm dynamisch mit Objekten arbeiten muss, d.h. wenn sie während der Programmausführung erstellt oder gelöscht werden. Wenn Sie im Voraus wissen, welche und wie viele Objekte in Ihrem Programm benötigt werden, brauchen Sie keine dynamischen Zeiger. Aber wenn Sie nicht viele Objekte haben, ist es einfacher, sie in einer Schleife mit new zu erstellen.

Ganz genau! Und selbst in diesem Fall können Sie auf Zeiger verzichten.
 
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;
  }
//+------------------------------------------------------------------+


Ihre Klasse ist zu 90 % überflüssig. Nur zwei Funktionen führen die Hauptarbeit aus, das sind Openorders und tip Warum verwenden Sie Sel, Buy SelStop usw., wenn sie alle nur Openorders aufrufen? Außerdem wird der Auftragstyp als int übergeben, ist also nicht geschützt. Anstelle von int sollten Sie entweder Ihre eigene Aufzählung oder den Standard ENUM_ORDER_TYPE verwenden. Und im Allgemeinen sollten Sie besser nie die magischen Zahlen "1", "2" usw. verwenden, sondern nur Aufzählungen. Dadurch wird verhindert, dass Sie den linken Bestellwert an die Funktion senden. Die Funktion Openorders selbst ist zu groß. Sie besteht natürlich aus zwei Blöcken, dem Block der Geschäftsabschlüsse und dem Block der Überprüfung der Bedingungen. Jede dieser Funktionen sollte eine separate private Funktion sein.

Das ist ein guter Anfang, aber es gibt noch viel zu lernen. Die Tippfunktion lässt sich besser wie folgt umschreiben:

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


Welche Besonderheiten sind erforderlich? Überall gilt der gleiche Grundsatz: Alles muss so einfach wie möglich sein. Man muss nicht in die Wildnis gehen, nur um in der Wildnis zu sein. Wenn ein Problem einfach gelöst werden kann, sollte es auch einfach gelöst werden.

Dynamische Zeiger werden benötigt, wenn das Programm dynamisch mit Objekten arbeiten muss: Erstellen, Löschen während des Programmablaufs. Wenn Sie im Voraus wissen, welche und wie viele Objekte in Ihrem Programm benötigt werden, brauchen Sie keine dynamischen Zeiger. Aber außer wenn es so viele Objekte gibt, ist es einfacher, sie in einer Schleife über new zu erstellen.

Zeiger sind unverzichtbar für komplexe Objektkonvertierungen, bei denen eine dynamische Typidentifizierung erforderlich ist.