초보자의 질문 MQL5 MT5 MetaTrader 5 - 페이지 1333

 
Mikhail Tkachev :

답변 감사합니다, 당신은 전혀 악하지 않습니다)
이제 명확해졌습니다.)
UPD
이 디자인은 또한 작동합니다

At() 메서드가 반환하는 내용을 확인하십시오. NULL을 반환하면 치명적인 오류 와 함께 충돌합니다. 포인터로 객체에 접근하기 전에 NULL이 아닌지 확인하십시오.

 
Mikhail Tkachev :

이미 주목)
따라서 탈출구는 전역적으로 빈 객체를 선언하는 것입니다....
그리고 미리 알 수 없다면 몇 개나 될까요? "여백이 있음"으로 선언하시겠습니까? :)
추신 내장 도움말에서 개체를 선언하는 그런 방법을 찾지 못했습니다

일단 Artyo가 나에게 이 수업을 썼습니다. 어떻게 작동하는지 자세히 설명할 수 없습니다. 그러나 Artyom은 그것을 보면 기억하고 설명할 수 있을 것입니다. 일반적으로 다음은 클래스 자체입니다.

 #include <Arrays\ArrayObj.mqh>
/********************************************************************\
|   Класс Новый бар                                                  |
\********************************************************************/
class CNewBar : public CObject
  {
private :
   string             m_symbol;
   ENUM_TIMEFRAMES    m_timeframe;
   datetime           m_time;
   datetime           Time( void );                                       //  Возвращает время нулевого бара
   string              Symbol ( void )         { return this .m_symbol;    }
public :
   ENUM_TIMEFRAMES    Timeframe( void )      { return this .m_timeframe; }
   datetime           GetTime( void )        { return this .m_time;      } //  Возвращает время последнего обращения
   bool               IsNewBar( void );                                   //  Основная функция класса

                    CNewBar( const string symbol, const ENUM_TIMEFRAMES timeframe);
                   ~CNewBar( void ){;}
  };
//+------------------------------------------------------------------+
//|    Конструктор                                                   |
//+------------------------------------------------------------------+
CNewBar::CNewBar( const string symbol, const ENUM_TIMEFRAMES timeframe) : m_time( 0 )
  {
   this .m_symbol = symbol;
   this .m_timeframe = (timeframe == PERIOD_CURRENT ? Period () : timeframe);
  }
//+------------------------------------------------------------------+
//| CNewBar Time Возвращает время нулевого бара                      |
//+------------------------------------------------------------------+
datetime CNewBar::Time( void )
  {
   datetime array[ 1 ], ret;
   ret = CopyTime ( this .m_symbol, this .m_timeframe, 0 , 1 , array) == 1 ? array[ 0 ] : 0 ;
   return (array[ 0 ]);
  }
//+------------------------------------------------------------------+
//| CNewBar IsNewBar Основная функция класса                         |
//+------------------------------------------------------------------+
bool CNewBar::IsNewBar( void )
  {
   datetime tm = this .Time();
   if (tm == 0 )
       return false ;
   if (tm != this .m_time)
     {
       this .m_time = tm;
       return true ;
     }
   return false ;
  }

그리고 다음은 OnInit()에서 포인터를 생성하는 루프입니다.

   for ( int i = 0 ; i < ArraySize (Rates); i++)
     {
       CNewBar* nb = new CNewBar(Rates[i].m_Symbols, timefram);
       if (nb != NULL )
         {
          list_new_bar.Add(nb);
           Print (nb.IsNewBar(), " ***** " , Rates[i].m_Symbols, " ***** " , nb.Time());
         }
     }

그리고 OnTimer()

 void OnTimer ()
{
 int total = list_new_bar.Total();
 for ( int i = 0 ; i < ArraySize (Rates); i++)
  {
   CNewBar* nb = list_new_bar.At(i);
   if (nb == NULL )
     continue ;
   bool new_bar = nb.IsNewBar();
   if (new_bar)
    {// и дальше………

ArraySize(Rates)는 작업할 문자를 나열하는 구조 배열의 크기입니다 .

 
Alexey Viktorov :

일단 Artyo가 나에게 이 수업을 썼습니다. 어떻게 작동하는지 자세히 설명할 수 없습니다. 그러나 Artyom은 그것을 보면 기억하고 설명할 수 있을 것입니다. 일반적으로 다음은 클래스 자체입니다.

그리고 다음은 OnInit()에서 포인터를 생성하기 위한 루프입니다.

그리고 OnTimer()

ArraySize(Rates)는 작업할 문자를 나열하는 구조 배열의 크기입니다 .

여기:

 for ( int i = 0 ; i < ArraySize (Rates); i++)

나는 전체를 할 것입니다 - 단지 당신이 Rates 배열에서 문자를 읽기 때문에(맞나요?), 새로운 바 클래스의 인스턴스를 생성하고 그것들을 목록에 추가하십시오.

추가 오류의 경우 새 막대 클래스의 인스턴스에 대한 포인터 목록의 크기는 Rates 배열의 크기와 일치하지 않습니다.

일반적으로 다음과 같습니다.

 void OnTimer ()
  {
   int total = list_new_bar.Total();
   for ( int i = 0 ; i < total; i++)
   {
   CNewBar* nb = list_new_bar.At(i);
   if (nb == NULL )
       continue ;
   if (nb.IsNewBar())
     { // и дальше………

그리고 여기에서 목록에 추가 성공 여부도 확인해야 합니다.

   for ( int i = 0 ; i < ArraySize (Rates); i++)
     {
       CNewBar* nb = new CNewBar(Rates[i].m_Symbols, timefram);
       if (nb != NULL )
         {
          list_new_bar.Add(nb);
           Print (nb.IsNewBar(), " ***** " , Rates[i].m_Symbols, " ***** " , nb.Time());
         }
     }

이 같은:

   for ( int i = 0 ; i < ArraySize (Rates); i++)
     {
      CNewBar *nb = new CNewBar(Rates[i].m_Symbols, timefram);
       if (nb== NULL )
         continue ;
       if (!list_new_bar.Add(nb))
        {
         delete nb;
         continue ;
        }
       Print (nb.IsNewBar(), " ***** " , Rates[i].m_Symbols, " ***** " , nb.Time());
     }
목록에 새 개체에 대한 포인터를 추가하는 데 실패할 때 메모리 누수를 방지하기 위해
 
Artyom Trishkin :

여기:

나는 전체를 할 것입니다 - 단지 당신이 Rates 배열에서 문자를 읽기 때문에(맞나요?), 새로운 바 클래스의 인스턴스를 생성하고 그것들을 목록에 추가하십시오.

추가 오류의 경우 새 막대 클래스의 인스턴스에 대한 포인터 목록의 크기는 Rates 배열의 크기와 일치하지 않습니다.

일반적으로 다음과 같습니다.

그리고 여기에서 목록에 추가 성공 여부도 확인해야 합니다.

이 같은:

목록에 새 개체에 대한 포인터를 추가하는 데 실패할 때 메모리 누수를 방지하기 위해

고맙습니다. 이해합니다, 이렇게 수정 하겠습니다... :))))

나는 계속 문을 싫어한다 ; 그리고 그것을 사용하지 마십시오. 비상 상황에서만.

       if (nb== NULL )
         continue ;

와 어떻게 다른가요

       if (nb!= NULL )
       {
       }
또 다른 것은 오류의 경우 실패한 포인터가 삭제되는 경우 ... 그러나 여기에서도 계속하지 않고 할 수 있습니다. 나는 싫어합니다. 간단히 Print()를 제거하면 됩니다. 디버깅을 하고 무슨 일이 일어났는지 이해하려고 하는 과정에서 필요했고, 동작 중에 에러가 나면 누구에게나 잘못됐는지 이해가 안 갑니다... 로그를 이해하는 것보다 OS를 재설치하는 것이 더 쉽습니다.


우리는 이미 이것에 대해 이야기하고 있기 때문에, 그냥 넘어가지 않고 포인터가 클래스 변수와 어떻게 다른지, 그리고 어떤 것이 더 좋은지 알려주십시오. 이해하기 어려운 세부 사항은 tyrnet에서 읽을 수 있습니다. 말하자면 피상적인 이해면 충분합니다 ...

 
Artyom Trishkin :

At() 메서드가 반환하는 내용을 확인하세요. NULL을 반환하면 치명적인 오류 와 함께 충돌합니다. 포인터로 객체에 접근하기 전에 NULL이 아닌지 확인하십시오.

Artem, 귀중한 의견 감사합니다)

 
Alexey Viktorov :

고맙습니다. 이해합니다, 이렇게 수정 하겠습니다... :))))

나는 계속 문을 싫어한다 ; 그리고 그것을 사용하지 마십시오. 비상 상황에서만.

와 어떻게 다른가요


루프의 반복은 끝나지 않고 새로운 반복은 시작되지 않지만 다음 If로 이동합니다. 논리가 바뀔 것입니다.

 
Alexey Viktorov :

일단 Artyo가 나에게 이 수업을 썼습니다. 어떻게 작동하는지 자세히 설명할 수 없습니다. 그러나 Artyom은 그것을 보면 기억하고 설명할 수 있을 것입니다. 일반적으로 다음은 클래스 자체입니다.

 //+------------------------------------------------------------------+
//| CNewBar Time Возвращает время нулевого бара                      |
//+------------------------------------------------------------------+
datetime CNewBar::Time( void )
  {
   datetime array[ 1 ], ret;
   ret = CopyTime ( this .m_symbol, this .m_timeframe, 0 , 1 , array) == 1 ? array[ 0 ] : 0 ;
   return (array[ 0 ]);
 }

Alex, 자세한 답변 감사합니다.
위의 코드 조각에서 ret 변수의 목적이 명확하지 않습니다...
어쨌든 메서드가 array[0]을 반환하면 왜 계산됩니까?
Z.Y.
클래스 메서드 에서 이것을 사용하는 이유는 무엇입니까? 우리는 이 특정 클래스의 멤버들과 함께 일하고 있습니다...


 
Alexey Viktorov :

고맙습니다. 이해합니다, 이렇게 수정 하겠습니다... :))))

나는 계속 문을 싫어한다 ; 그리고 그것을 사용하지 마십시오. 비상 상황에서만.

와 어떻게 다른가요

또 다른 것은 오류의 경우 실패한 포인터가 삭제되는 경우 ... 그러나 여기에서도 계속하지 않고 할 수 있습니다. 나는 싫어합니다. 간단히 Print()를 제거하면 됩니다. 디버깅을 하고 무슨 일이 일어났는지 이해하려고 하는 과정에서 필요했고, 동작 중에 에러가 나면 누구에게나 잘못됐는지 이해가 안 갑니다... 로그를 이해하는 것보다 OS를 재설치하는 것이 더 쉽습니다.


우리는 이미 이것에 대해 이야기하고 있기 때문에, 그냥 넘어가지 않고 포인터가 클래스 변수와 어떻게 다른지, 그리고 어떤 것이 더 좋은지 알려주십시오. 이해하기 어려운 세부 사항은 tyrnet에서 읽을 수 있습니다. 말하자면 피상적인 이해면 충분합니다 ...

나는 사다리와 가지를 울타리로 묶지 않도록 불필요한 브래킷을 제거하려고 노력합니다. 인쇄가 없으면 대괄호가 필요하지 않습니다. 개체를 삭제하면 그대로 남습니다.

새 연산자에서 물리적으로 "어딘가"에 있는 특정 메커니즘을 만듭니다. new 연산자는 이 "어딘가"의 주소를 반환합니다. 그리고 그것에 대해서만이 "메커니즘"으로 돌릴 수 있습니다.
그리고 이 메커니즘 내부의 볼트는 변수입니다.
 
Valeriy Yastremskiy :

루프의 반복은 끝나지 않고 새로운 반복은 시작되지 않지만 다음 If로 이동합니다. 논리가 바뀔 것입니다.

루프의 새로운 반복으로 이동합니다.
 
Mikhail Tkachev :

Alex, 자세한 답변 감사합니다.
위의 코드 조각에서 ret 변수의 목적이 명확하지 않습니다...
어쨌든 메서드가 array[0]을 반환하면 왜 계산됩니까?


내가 준 코드에서 무언가를 변경한 것은 Aleksey였습니다. 아니면 제가 간과했을 수도 있습니다. 설명을 위한 간단한 예로 "무릎 위에"라고 썼습니다. 기억이 나지 않습니다.
사유: