Domande dai principianti MQL5 MT5 MetaTrader 5 - pagina 1333

 
Mikhail Tkachev:

Grazie per la risposta, non sei affatto cattivo)
Ora tutto ha senso)
UPD
Anche questa costruzione funziona

Fate attenzione a cosa restituisce il metodo At(). Se restituisce NULL, andrete in crash per un errore critico. Prima di accedere a un puntatore a un oggetto, controllare che non sia NULL

 
Mikhail Tkachev:

Già notato)
Quindi la soluzione è dichiarare oggetti globalmente vuoti....
E se non si sa in anticipo quanti ce ne saranno? Basta dichiarare "con riserva"? :)
P.S. Non ho trovato questo modo di dichiarare oggetti nell'aiuto integrato

Una volta Artyom mi ha scritto questa lezione. Non posso spiegare in dettaglio come funziona. Ma Artem si ricorderà e sarà in grado di spiegare. Ecco la classe stessa

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

Ed ecco il ciclo di creazione dei puntatori 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());
         }
     }

e 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) è la dimensione dell'array di strutture in cui sono elencati i caratteri da lavorare.

 
Alexey Viktorov:

Artyom una volta mi ha scritto questa lezione. Non posso spiegare in dettaglio come funziona. Ma Artyom si ricorderà e sarà in grado di spiegare. Bene, ecco la classe stessa

Ed ecco il ciclo di creazione dei puntatori in OnInit()

e in OnTimer()

ArraySize(Rates) è la dimensione dell'array di strutture in cui sono elencati i caratteri da lavorare.

Qui:

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

Io farei prima del totale - semplicemente per la ragione che stai leggendo i caratteri dall'array Rates (giusto?), creando istanze della nuova classe bar e aggiungendole alla lista.

In qualsiasi errore di aggiunta, la dimensione dell'elenco di puntatori alle istanze della nuova classe bar non corrisponderà alla dimensione dell'array Rates.

In generale, deve essere qualcosa del genere:

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

Ed è qui che bisogna controllare anche l'aggiunta di successo alla lista:

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

qualcosa del genere:

   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());
     }
per evitare perdite di memoria quando un puntatore a un nuovo oggetto viene aggiunto per errore alla lista
 
Artyom Trishkin:

Qui:

Io farei prima del totale - semplicemente per il motivo che si leggono i caratteri dall'array Rates (giusto?), si creano istanze della nuova classe bar e si aggiungono alla lista.

In qualsiasi errore di aggiunta, la dimensione dell'elenco di puntatori alle istanze della nuova classe bar non corrisponderà alla dimensione dell'array Rates.

In generale, deve essere qualcosa del genere:

Ed è qui che bisogna controllare anche l'aggiunta di successo alla lista:

qualcosa del genere:

per evitare perdite di memoria quando un puntatore a un nuovo oggetto viene aggiunto per errore alla lista

Grazie. Ho capito, lo correggo in questo modo:)))

Odio il continue; operator e cerco di non usarlo. Esclusivamente nei casi senza speranza.

      if(nb==NULL)
         continue;

come si differenzia da

      if(nb!=NULL)
       {
       }
Un'altra cosa è se all'errore il puntatore fallito viene cancellato... Ma anche qui possiamo fare a meno dell'odiato continue; semplicemente cancellando Print(). Era necessario durante il debug e cercando di capire cosa sta succedendo, e se durante il lavoro succede qualche errore, non capirò comunque cosa c'è di sbagliato... È più facile reinstallare il sistema operativo che capire i log.


Visto che siamo in tema, per favore diteci, senza entrare nei dettagli, qual è la differenza tra un puntatore e una variabile di classe, e quale è preferibile. Posso leggere su Internet con dettagli difficili da capire. Una comprensione superficiale mi basta, per così dire...

 
Artyom Trishkin:

Fate attenzione a cosa restituisce il metodo At(). Se restituisce NULL, andrete in crash per un errore critico. Prima di accedere a un puntatore a un oggetto, controllate che non sia NULL.

Artem, grazie per il prezioso commento)

 
Alexey Viktorov:

Grazie. Ho capito, lo sistemerò così... :)))

Odio l'operatore continue; e cerco di non usarlo. Esclusivamente nei casi senza speranza.

Come si differenzia da


L'iterazione del ciclo non finirà e non ne inizierà una nuova, ma passerà alla prossima iterazione. La logica cambierà.

 
Alexey Viktorov:

Artyom una volta mi ha scritto questa lezione. Non posso spiegare in dettaglio come funziona. Ma Artyom si ricorderà e sarà in grado di spiegare. Comunque, ecco la classe stessa

//+------------------------------------------------------------------+
//| 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, grazie per una risposta così dettagliata.
Lo scopo della variabile ret nel frammento di codice citato non è chiaro...
Per quale motivo viene calcolato, se in ogni caso il metodo restituisce array[0]?
P.S.
E perché usare questo in un metodo di classe? Stiamo lavorando con i membri di questa particolare classe...


 
Alexey Viktorov:

Grazie. Ho capito, lo sistemerò così... :)))

Odio l'operatore continue; e cerco di non usarlo. Esclusivamente nei casi senza speranza.

come si differenzia da

Un'altra cosa è se, quando si verifica un errore, si cancella il puntatore fallito... Ma anche qui si può fare a meno dell'odiato continue; basta cancellare Print(). Era necessario durante il debug e cercando di capire cosa sta succedendo, e se durante il lavoro si verifica qualche errore, non capirò comunque cosa c'è di sbagliato... Preferisco reinstallare il sistema operativo che capire i log.


Visto che siamo in tema, per favore diteci, senza entrare nei dettagli, qual è la differenza tra un puntatore e una variabile di classe, e quale è preferibile. Posso leggere su Internet con dettagli difficili da capire. Una comprensione superficiale è sufficiente per me, per così dire.

Sto cercando di sbarazzarmi delle parentesi inutili - così non faccio foreste e rami. Senza la stampa, non hai bisogno di parentesi - cancelli semplicemente l'oggetto.

Con il nuovo operatore si crea qualche meccanismo che si trova fisicamente "da qualche parte". Il nuovo operatore restituisce l'indirizzo di questo "da qualche parte". Ed è l'unico modo in cui ci si può riferire a questo "meccanismo".
E il bullone all'interno di quel meccanismo è una variabile.
 
Valeriy Yastremskiy:

L'iterazione del ciclo non finirà e non ne inizierà una nuova, ma passerà al prossimo Se. La logica cambierà.

Effettua una transizione a una nuova iterazione del ciclo, all'interno della quale è
 
Mikhail Tkachev:

Alexey, grazie per una risposta così dettagliata.
Lo scopo della variabile ret nel frammento di codice dato non è chiaro...
Perché viene calcolato se il metodo restituisce comunque array[0]?


Alexey ha rielaborato qualcosa nel codice che ho dato. O forse l'ho perso anch'io - l'ho scritto "in ginocchio" come semplice esempio per spiegare ciò che non ricordo più.
Motivazione: