Questions on OOP (Object Oriented Programming) - page 5

 
VOLDEMAR:

I have now redesigned my class

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);
  }
And added inheritance ... ( I suspect I may be wrong ) from the vr_MarketInfo class

The vr_MarketInfo class returns information about Point, Digits for the symbol and checks the lot for errors, and many other things I need for work including keeping a log in Excel and on a chart

When using a method like above a list is given when working in Primer.Primer.Primer()

I would like to do something more abbreviated...

Where is the inheritance? What's the point of the pointer?

 
Zhunko:

Where is the inheritance? What is the point of the pointer?


Write a textbook on MQL4+. Cooperate, connoisseurs, and write it. 50 bucks :)
 
In fact, the textbook and documentation are not very specific about the use of pointers or the new operator. We can either guess or wait for the weather to pass. Or when somebody accidentally says something somewhere. I am shocked at how things work. It's also interesting that except for me and the topicstarter VLadimir nobody seems to need anything. Although I still believe that many people do not understand this topic. And that's why they don't get into such questions...
 
tara:

Write a textbook on MQL4+. Cooperate, connoisseurs, and write it. 50 bucks :)

Everything was written a long time ago.

MQL4 == C++ with slight limitations.

 
hoz:
As a matter of fact, neither the manual, nor the documentation offers any specifics on how to use pointers, or the new operator. We can either guess or wait for the weather to pass. Or when somebody accidentally says something somewhere. I am shocked how it happens. It's also interesting that except for me and the topicstarter VLadimir nobody seems to need anything. Although I still believe that many people do not understand this topic. And that is why they don't pry into such questions...


What kind of specifics do you need? One principle applies everywhere: keep things as simple as possible. Don't go into the thick of things just to be in the thick of things. If a problem can be solved simply, it must be solved simply.

Dynamic pointers are needed if your program needs to dynamically work with objects: create, delete during the running of the program. If you know beforehand which and how many objects are needed in the program, you don't need dynamic pointers. But unless you have a lot of objects, you can simply create them in a loop with new.


 
VOLDEMAR:
I for example find it hard to learn the theory, show me an example and describe how functions define circle, square, trapezoid or triangle.

One of the articles linked in the first post has this example.

A base class with a virtual method. The descendant has a method with the same name, in which the calculations are made.

 
VOLDEMAR:
I for one find it hard to learn the theory, show me an example, and describe how functions define a circle, a square, a trapezoid, or a triangle ???


I leave trapezoid and triangle to my own work:

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

Dynamic pointers are needed if the program needs to work with objects dynamically: creating, deleting them during the program operation. If you know in advance which and how many objects will be needed in the program, you don't need dynamic pointers. But unless you have a lot of objects, it's easier to create them in a loop with new.

Exactly! And even in that case you can do without pointers.
 
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;
  }
//+------------------------------------------------------------------+


Your class is 90% redundant. Only two functions perform the main work, these are openorders and tip Why do you use Sel, Buy SelStop, etc., when in fact they all just call Openorders? Furthermore, the order type is passed as int, so it's not protected. Instead of int you'd better use either your own enumeration or the standard ENUM_ORDER_TYPE. And in general, you'd better never use magic numbers "1", "2" etc., only enumerations. This will prevent you from sending the left order value to the function. The Openorders function itself is too big. Obviously, it consists of two blocks, the block of making a deal and the block of checking conditions. Each of them should be as a separate private function.

It's a good start, but there's still a lot to learn. The tip function would be better rewritten as follows:

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


What specifics are needed? The same principle applies everywhere: everything must be done as simply as possible. You don't have to go into the wilderness just to be in the wilderness. If a problem can be solved simply, it should be solved simply.

Dynamic pointers are needed if the program needs to dynamically work with objects: creating, deleting during the program operation. If you know in advance which and how many objects will be needed in the program, you don't need dynamic pointers. But except when there are so many objects, it's easier to create them in a loop via new.

Pointers are indispensable for complex object conversions where dynamic type identification is required.
Reason: