Perguntas de Iniciantes MQL5 MT5 MetaTrader 5 - página 1333

 
Mikhail Tkachev:

Obrigado pela resposta, você não é nada mau)
Agora tudo faz sentido)
UPD
Esta construção também funciona

Preste atenção ao que o método At() devolve. Se devolver o NULL, irá cair em erro crítico. Antes de aceder a um ponteiro para um objecto, verifique se não é NULL

 
Mikhail Tkachev:

Já notado)
Portanto, a solução é declarar globalmente objectos vazios....
E se não souber de antemão quantos deles haverá? Basta declarar "com reserva" ? :)
P.S. Não encontrei esta forma de declarar objectos na ajuda integrada

Era uma vez Artyom escreveu-me esta aula. Não consigo explicar em detalhes como funciona. Mas Artem lembrar-se-á e será capaz de explicar. Aqui está a classe em si

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

E aqui está o ciclo de criação de apontadores no 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 em 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) é o tamanho do conjunto de estruturas em que os caracteres com os quais trabalhar são listados.

 
Alexey Viktorov:

Artyom escreveu-me uma vez esta aula. Não consigo explicar em detalhe como funciona. Mas Artyom lembrar-se-á e será capaz de explicar. Aqui está a classe em si

E aqui está o ciclo de criação de apontadores no OnInit()

e em OnTimer()

ArraySize(Rates) é o tamanho do conjunto de estruturas onde estão listados os caracteres com os quais se deve trabalhar.

Aqui:

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

Eu faria antes do total - simplesmente pela razão de estar a ler caracteres da tabela de Tarifas (certo?), criando instâncias da nova classe de barras e adicionando-as à lista.

Em qualquer erro de adição, o tamanho da lista de apontadores para instâncias da nova classe de barras não corresponderá ao tamanho da matriz de Tarifas.

Em geral, deve ser algo parecido com isto:

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

E é aqui que também precisa de verificar se a lista foi acrescentada com sucesso:

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

algo parecido com isto:

   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());
     }
para evitar fugas de memória quando um ponteiro para um novo objecto é adicionado à lista por engano
 
Artyom Trishkin:

Aqui:

Eu faria antes do total - simplesmente pela razão de que lê caracteres da matriz de Tarifas (certo?), criar instâncias da nova classe de barras e adicioná-las à lista.

Em qualquer erro de adição, o tamanho da lista de apontadores para instâncias da nova classe de barras não corresponderá ao tamanho da matriz de Tarifas.

Em geral, deve ser algo parecido com isto:

E é aqui que também precisa de verificar se a lista foi acrescentada com sucesso:

algo parecido com isto:

para evitar fugas de memória quando um ponteiro para um novo objecto é adicionado à lista por engano

Obrigado. Já o tenho, vou corrigi-lo desta forma:))))

Detesto continuar; operador e tente não o utilizar. Exclusivamente em casos desesperados.

      if(nb==NULL)
         continue;

como difere de

      if(nb!=NULL)
       {
       }
Outra coisa é se por erro o ponteiro falhado for apagado... Mas mesmo aqui podemos fazer sem odiar continuar; simplesmente apagando Print(). Foi necessário durante a depuração e a tentativa de compreender o que se está a passar, e se durante o trabalho acontecer algum erro, não vou entender o que está errado de qualquer maneira... É mais fácil reinstalar o SO do que compreender os registos.


Já que estamos a falar do assunto, diga-nos, sem entrar em detalhes, qual é a diferença entre um ponteiro e uma variável de classe, e qual é preferível. Posso ler sobre isso na Internet em detalhes que são difíceis de compreender. Um entendimento superficial é suficiente para mim, por assim dizer.

 
Artyom Trishkin:

Preste atenção ao que o método At() retorna. Se devolver o NULL, irá cair em erro crítico. Antes de aceder a um ponteiro para um objecto, verificar que não é NULL.

Artem, obrigado pelo valioso comentário)

 
Alexey Viktorov:

Obrigado. Já percebi, vou arranjá-lo assim... :)))

Odeio o operador contínuo; e tento não o utilizar. Exclusivamente em casos desesperados.

Como difere de


A iteração do loop não terminará e não iniciará uma nova, mas avançará para a próxima iteração. A lógica irá mudar.

 
Alexey Viktorov:

Artyom escreveu-me uma vez esta aula. Não consigo explicar em detalhe como funciona. Mas Artyom lembrar-se-á e será capaz de explicar. De qualquer forma, aqui está a própria turma

//+------------------------------------------------------------------+
//| 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, obrigado por uma resposta tão detalhada.
O objectivo da variável ret no fragmento de código citado não é claro...
Para que é calculado, se em qualquer caso o método retorna matriz[0] ?
P.S.
E porquê utilizá-lo num método de classe? Estamos a trabalhar com membros desta classe em particular...


 
Alexey Viktorov:

Obrigado. Já percebi, vou arranjá-lo assim... :)))

Odeio o operador contínuo; e tento não o utilizar. Exclusivamente em casos desesperados.

como difere de

Outra coisa é se, quando ocorre um erro, se apagar o ponteiro falhado... Mas também aqui se pode fazer sem odiar continuar; basta apagar Print(). Foi necessário durante a depuração e a tentativa de compreender o que se está a passar, e se durante o trabalho acontecer algum erro, eu não vou entender o que está errado de qualquer maneira... Prefiro reinstalar o SO do que compreender os registos.


Já que estamos a falar do assunto, diga-nos, sem entrar em detalhes, qual é a diferença entre um ponteiro e uma variável de classe, e qual é preferível. Posso ler sobre isso na Internet em detalhes que são difíceis de compreender. Um entendimento superficial é suficiente para mim, por assim dizer.

Estou a tentar livrar-me de parênteses desnecessários - para não fazer florestas e ramos. Sem a impressão não há necessidade de parênteses - basta apagar o objecto.

Com o novo operador cria-se um mecanismo que se encontra fisicamente "algures". O novo operador devolve o endereço deste "algures". E esta é a única forma de se referir a este "mecanismo".
E o parafuso dentro desse mecanismo é uma variável.
 
Valeriy Yastremskiy:

A iteração do ciclo não terminará e não iniciará um novo ciclo, mas passará para o próximo Se. A lógica irá mudar.

Faz uma transição para uma nova iteração do ciclo, dentro da qual se
 
Mikhail Tkachev:

Alexey, obrigado por uma resposta tão detalhada.
A finalidade da variável ret no fragmento de código dado não é clara...
Porque é que é calculado se o método retorna matriz[0] de qualquer maneira?


Alexey reelaborou algo no código que eu dei. Ou talvez também o tenha perdido - escrevi-o "de joelhos" como um simples exemplo para explicar aquilo de que já não me lembro.