Fragen von Anfängern MQL5 MT5 MetaTrader 5 - Seite 1333

 
Mikhail Tkachev:

Danke für die Antwort, du bist gar nicht böse)
Jetzt macht das alles Sinn)
UPD
Diese Konstruktion funktioniert auch

Achten Sie darauf, was die Methode At() zurückgibt. Wenn es NULL zurückgibt, stürzt man bei einem kritischen Fehler ab. Vor dem Zugriff auf einen Zeiger auf ein Objekt ist zu prüfen, ob dieser nicht NULL ist

 
Mikhail Tkachev:

Bereits bemerkt)
Die Lösung besteht also darin, global leere Objekte zu deklarieren....
Und wenn man vorher nicht weiß, wie viele es sein werden? Einfach "mit Reserve" deklarieren ? :)
P.S. Ich habe diese Art der Deklaration von Objekten nicht in der integrierten Hilfe gefunden

Vor einiger Zeit schrieb mir Artyom diesen Kurs. Ich kann nicht im Detail erklären, wie es funktioniert. Aber Artem wird sich daran erinnern und wird es erklären können. Hier ist die Klasse selbst

#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;
  }

Und hier ist die Schleife zur Erstellung von Zeigern in 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());
         }
     }

und in 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) ist die Größe des Arrays von Strukturen, in denen die zu bearbeitenden Zeichen aufgelistet sind.

 
Alexey Viktorov:

Artyom schrieb mir einmal diese Klasse. Ich kann nicht im Detail erklären, wie es funktioniert. Aber Artyom wird sich daran erinnern und wird es erklären können. Hier ist die Klasse selbst

Und hier ist die Schleife zur Erstellung von Zeigern in OnInit()

und in OnTimer()

ArraySize(Rates) ist die Größe des Arrays von Strukturen, in dem die zu bearbeitenden Zeichen aufgelistet sind.

Hier:

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

Ich würde vor insgesamt tun - einfach aus dem Grund, dass Sie Zeichen aus dem Array Rates (richtig?) lesen, Instanzen der neuen Bar-Klasse erstellen und sie der Liste hinzufügen.

Bei einem Additionsfehler stimmt die Größe der Liste von Zeigern auf Instanzen der neuen Balkenklasse nicht mit der Größe des Arrays Rates überein.

Im Allgemeinen muss es in etwa so aussehen:

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())
     {// и дальше………

Und auch hier müssen Sie prüfen, ob Sie die Liste erfolgreich ergänzen können:

   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());
         }
     }

etwa so:

   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());
     }
um Speicherlecks zu vermeiden, wenn ein Zeiger auf ein neues Objekt versehentlich zur Liste hinzugefügt wird
 
Artyom Trishkin:

Hier:

Ich würde vor insgesamt tun - einfach aus dem Grund, dass Sie Zeichen aus dem Array Rates lesen (richtig?), erstellen Sie Instanzen der neuen bar-Klasse und fügen Sie sie der Liste.

Bei einem Additionsfehler stimmt die Größe der Liste von Zeigern auf Instanzen der neuen Balkenklasse nicht mit der Größe des Arrays Rates überein.

Im Allgemeinen muss es in etwa so aussehen:

Und auch hier müssen Sie prüfen, ob Sie die Liste erfolgreich ergänzen können:

etwa so:

um Speicherlecks zu vermeiden, wenn ein Zeiger auf ein neues Objekt versehentlich zur Liste hinzugefügt wird

Danke. Ich habe es verstanden, ich werde es so korrigieren:)))

Ich hasse continue; operator und versuche, es nicht zu benutzen. Ausschließlich in hoffnungslosen Fällen.

      if(nb==NULL)
         continue;

wie sie sich unterscheidet von

      if(nb!=NULL)
       {
       }
Eine andere Sache ist, wenn bei einem Fehler der fehlgeschlagene Zeiger gelöscht wird... Aber auch hier können wir auf das verhasste Continue verzichten; einfach durch Löschen von Print(). Es wurde während der Fehlersuche benötigt, und wenn während der Arbeit ein Fehler auftritt, verstehe ich sowieso nicht, was los ist... Es ist einfacher, das Betriebssystem neu zu installieren als die Protokolle zu verstehen.


Da wir gerade beim Thema sind, sagen Sie mir bitte, ohne ins Detail zu gehen, was der Unterschied zwischen einem Zeiger und einer Klassenvariablen ist und was vorzuziehen ist. Ich kann im Internet Details darüber lesen, die schwer zu verstehen sind. Ein oberflächliches Verständnis reicht mir sozusagen aus...

 
Artyom Trishkin:

Achten Sie darauf, was die Methode At() zurückgibt. Wenn es NULL zurückgibt, stürzt man bei einem kritischen Fehler ab. Vor dem Zugriff auf einen Zeiger auf ein Objekt ist zu prüfen, ob dieser nicht NULL ist.

Artem, danke für die wertvolle Bemerkung)

 
Alexey Viktorov:

Ich danke Ihnen. Ich verstehe, ich bringe das so in Ordnung... :)))

Ich hasse den "Continue"-Operator und versuche, ihn nicht zu benutzen. Ausschließlich in hoffnungslosen Fällen.

Wie unterscheidet sie sich von


Die Iteration der Schleife wird nicht beendet und es wird auch keine neue gestartet, sondern es wird zur nächsten Iteration übergegangen. Die Logik wird sich ändern.

 
Alexey Viktorov:

Artyom schrieb mir einmal diese Klasse. Ich kann nicht im Detail erklären, wie es funktioniert. Aber Artyom wird sich daran erinnern und wird es erklären können. Wie auch immer, hier ist die Klasse selbst

//+------------------------------------------------------------------+
//| 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]);
 }

Alexey, ich danke dir für deine ausführliche Antwort.
Der Zweck der ret-Variable in dem zitierten Codefragment ist unklar...
Wofür wird es berechnet, wenn die Methode auf jeden Fall array[0] zurückgibt?
P.S.
Und warum wird dies in einer Klassenmethode verwendet? Wir arbeiten mit Mitgliedern dieser besonderen Klasse...


 
Alexey Viktorov:

Ich danke Ihnen. Ich verstehe, ich bringe das so in Ordnung... :)))

Ich hasse den "Continue"-Operator und versuche, ihn nicht zu benutzen. Ausschließlich in hoffnungslosen Fällen.

wie sie sich unterscheidet von

Eine andere Sache ist, wenn Sie bei einem Fehler den fehlgeschlagenen Zeiger löschen... Aber auch hier können Sie auf das gehasste continue verzichten; löschen Sie einfach Print(). Es wurde während der Fehlersuche benötigt, und wenn während der Arbeit ein Fehler auftritt, verstehe ich sowieso nicht, was los ist... Lieber installiere ich das Betriebssystem neu, als die Protokolle zu verstehen.


Da wir gerade beim Thema sind, sagen Sie uns bitte, ohne ins Detail zu gehen, was der Unterschied zwischen einem Zeiger und einer Klassenvariablen ist und was vorzuziehen ist. Ich kann im Internet Details darüber lesen, die schwer zu verstehen sind. Ein oberflächliches Verständnis reicht mir sozusagen aus.

Ich versuche, unnötige Klammern loszuwerden - damit ich keine Wälder und Äste mache. Ohne den Ausdruck sind keine Klammern erforderlich - löschen Sie einfach das Objekt.

Mit dem neuen Operator schaffen Sie einen Mechanismus, der physisch "irgendwo" liegt. Der neue Operator gibt die Adresse dieses "irgendwo" zurück. Und nur so kann man diesen "Mechanismus" bezeichnen.
Und der Bolzen in diesem Mechanismus ist eine Variable.
 
Valeriy Yastremskiy:

Die Iteration des Zyklus endet nicht, und es beginnt auch keine neue, sondern es wird zum nächsten Wenn übergegangen. Die Logik wird sich ändern.

Ermöglicht einen Übergang zu einer neuen Iteration des Zyklus, in dem
 
Mikhail Tkachev:

Alexey, vielen Dank für diese ausführliche Antwort.
Der Zweck der ret-Variable in dem angegebenen Codefragment ist nicht klar...
Warum wird sie berechnet, wenn die Methode sowieso array[0] zurückgibt?


Alexey hat etwas in dem von mir angegebenen Code überarbeitet. Oder vielleicht habe ich es auch übersehen - ich habe es "auf meinen Knien" geschrieben, als einfaches Beispiel, um zu erklären, woran ich mich nicht mehr erinnere.
Grund der Beschwerde: