OOP(객체 지향 프로그래밍)에 대한 질문 - 페이지 5

 
VOLDEMAR :

이제 나는 수업을 다시 했어

 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 );
  }
그리고 vr_MarketInfo 클래스에서 상속을 추가했습니다 ... (제가 틀릴 수 있다고 생각합니다)

vr_MarketInfo 클래스는 포인트에 대한 정보, 기호의 숫자를 반환 하고 오류에 대한 로트를 확인하고 Excel 및 차트에 로그인하는 것을 포함하여 작업해야 하는 훨씬 더 많은 것을 확인합니다.

위와 같은 방법을 사용하면 Primer.Primer.Primer() Expert Advisor에서 작업할 때 목록이 반환됩니다.

좀 더 줄여서 하고 싶은데...

상속은 어디에 있습니까? 포인터의 요점은 무엇입니까?

 
Zhunko :

상속은 어디에 있습니까? 포인터의 요점은 무엇입니까?


MQL4+에 대한 자습서를 작성하십시오. 협력하고, 전문가에게, 그리고 쓰십시오. 50달러 여성 :)
 
그러나 사실, 그렇다면 교과서와 문서에는 포인터 사용이나 연산자에 대한 세부 사항이 없습니다. 추측하거나 바다의 날씨를 기다리는 것이 남아 있습니다. 또는 누군가가 실수로 어딘가에서 무언가를 말할 때. 나는 이것이 어떻게 일어나는지에 완전히 충격을 받았습니다. 나와 topikstarter Vladimir를 제외하고는 아무도 아무것도 필요로 하지 않는 것 같습니다. 나는 여전히 많은 사람들이 이 주제에 전혀 집착하지 않는다고 믿습니다. 그래서 그들은 이런 질문을 하지 않습니다.
 
tara :

MQL4+에 대한 자습서를 작성하십시오. 협력하고, 전문가에게, 그리고 쓰십시오. 50달러 여성 :)

모든 것이 오랫동안 쓰여졌습니다.

MQL4 == 사소한 제한이 있는 C++.

 
hoz :
그러나 사실, 그렇다면 교과서와 문서에는 포인터 사용이나 연산자에 대한 세부 사항이 없습니다. 추측하거나 바다의 날씨를 기다리는 것이 남아 있습니다. 또는 누군가가 실수로 어딘가에서 무언가를 말할 때. 나는 이것이 어떻게 일어나는지에 완전히 충격을 받았습니다. 나와 topikstarter Vladimir를 제외하고는 아무도 아무것도 필요로 하지 않는 것 같습니다. 나는 여전히 많은 사람들이 이 주제에 전혀 집착하지 않는다고 믿습니다. 그래서 그들은 이런 질문을 하지 않습니다.


어떤 세부 사항이 필요합니까? 어디에나 하나의 원칙이 있습니다. 모든 것이 가능한 한 간단하게 이루어져야 합니다. 야생에 있기 위해 야생에 올라갈 필요가 없습니다. 문제를 간단하게 해결할 수 있다면 간단하게 해결해야 합니다.

프로그램이 객체에 대한 동적 작업 (프로그램 작동 중 생성, 삭제)을 필요로 하는 경우 동적 포인터가 필요합니다. 프로그램에서 어떤 개체와 양이 필요한지 미리 알고 있으면 동적 포인터가 필요하지 않습니다. 그러나 객체가 많은 경우를 제외하고는 이 경우 new를 통해 루프로 생성하는 것이 더 쉽습니다.

 
VOLDEMAR :
예를 들어, 이론을 공부하고, 예를 보여주고, 함수가 원, 정사각형, 사다리꼴 또는 삼각형을 결정하는 방법을 설명하는 것이 어렵습니다 ???

첫 번째 게시물에 링크가 제공된 기사 중 하나에 그러한 예가 있습니다.

가상 메서드가 있는 기본 클래스. 자손에는 실제로 계산이 이루어지는 같은 이름의 방법이 있습니다.

 
VOLDEMAR :
예를 들어, 이론을 공부하고, 예를 보여주고, 함수가 원, 정사각형, 사다리꼴 또는 삼각형을 결정하는 방법을 설명하는 것이 어렵습니다 ???


나는 독립적 인 작업을 위해 사다리꼴과 삼각형을 남겨 둡니다.

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

동적 포인터는 물론, 프로그램이 개체에 대한 동적 작업을 필요로 하는 경우: 프로그램 작동 중 생성, 삭제. 프로그램에서 어떤 개체와 양이 필요한지 미리 알고 있으면 동적 포인터가 필요하지 않습니다. 그러나 객체가 많은 경우를 제외하고는 이 경우 new를 통해 루프로 생성하는 것이 더 쉽습니다.

정확히! 그리고 이 경우에도 포인터 없이 할 수 있습니다.
 
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;
  }
//+------------------------------------------------------------------+


당신의 수업은 90% 중복되었습니다. 두 가지 기능만 주요 작업 수행합니다. 팁 Sel, Buy SelStop 등을 사용하는 이유는 무엇입니까? 실제로는 모두 Openorders를 호출하기만 하면 됩니다. 또한 주문 유형은 보호되지 않음을 의미하는 int로 전달됩니다. int 대신 고유한 열거나 표준 ENUM_ORDER_TYPE 을 사용하는 것이 좋습니다. 그리고 일반적으로 마법의 숫자 "1", "2" 등을 사용하지 않고 열거형만 사용하는 것이 좋습니다. 이렇게 하면 주문의 왼쪽 값이 함수로 전송되는 것을 방지할 수 있습니다. Openorders 함수 자체가 너무 큽니다. 거래를 위한 블록과 조건을 확인하는 블록의 두 가지로 구성되어 있음을 알 수 있다. 각각은 별도의 private 함수 형태여야 합니다.

나쁜 시작은 아니지만 아직 배울 것이 많습니다. tip 함수는 다음과 같이 다시 작성하는 것이 좋습니다.

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


어떤 세부 사항이 필요합니까? 어디에나 하나의 원칙이 있습니다. 모든 것이 가능한 한 간단하게 이루어져야 합니다. 야생에 있기 위해 야생에 올라갈 필요가 없습니다. 문제를 간단하게 해결할 수 있다면 간단하게 해결해야 합니다.

프로그램이 객체에 대한 동적 작업(프로그램 작동 중 생성, 삭제)을 필요로 하는 경우 동적 포인터가 필요합니다. 프로그램에서 어떤 개체와 양이 필요한지 미리 알고 있으면 동적 포인터가 필요하지 않습니다. 그러나 객체가 많은 경우를 제외하고는 이 경우 new를 통해 루프로 생성하는 것이 더 쉽습니다.

포인터는 동적 유형 식별이 필요한 복잡한 개체 변환에 필수적입니다.