Discussão do artigo "Usando os Ponteiros de Objeto no MQL5"

 

Novo artigo Usando os Ponteiros de Objeto no MQL5 foi publicado:

Predefinidamente, todos os objetos no MQL5 são passados por referência, mas há a possibilidade de usar os ponteiros de objeto. Porém, é necessário realizar a verificação do ponteiro, porque o objeto pode não ser inicializado. Neste caso, o programa MQL5 será finalizado com o erro crítico e descarregado. Os objetos, criados automaticamente, não causam tal erro, então, neste sentido, são bastante seguros. Neste artigo, tentaremos entender a diferença entre a referência do objeto e o ponteiro do objeto, e considere como escrever o código seguro, que usa os ponteiros.


Autor: MetaQuotes Software Corp.

 

O código-fonte no texto deve ser alinhado com os arquivos anexados, em especial na listagem GetCriticalError_Unsafe.mq5, a referência é feita à variável inexistente status em vez de pstatus (como no arquivo).

E qual é o objetivo de definir seu próprio tipo de variável em cada uma das classes herdeiras do CShape?

E eu também gostaria de ouvir explicações sobre isso. Ao mudar do exemplo GetCriticalError_OnDemand para GetCriticalError_Unsafe, toda a alteração foi praticamente reduzida à mudança do tipo do argumento da função de CHello *pobject para CHello &pobject. Ao mesmo tempo, a chamada da função permaneceu inalterada - um ponteiro (CHello *) foi passado para lá. Nesse caso, de acordo com as palavras do autor,"recebemos um erro crítico novamente. A questão é que, se um objeto é passado por referência, o erro crítico ocorre no estágio de chamada de uma função em que um objeto não inicializado é passado para ela". Mas, nesse caso, um ponteiro é passado para a função, não uma referência. A questão é saber de onde ele vem. Você poderia explicar melhor as regras usadas pela MQL5 para a conversão implícita de ponteiros em referências e vice-versa? Ou indicar o local na documentação onde isso está descrito. Se o compilador suportasse tipagem estrita, o exemplo simplesmente não seria compilado devido à falta de uma função com um argumento do tipo necessário.

 
marketeer писал(а) # :

O código-fonte no texto deve ser alinhado com os arquivos anexados, em particular na listagem GetCriticalError_Unsafe.mq5 é feita referência a uma variável inexistente status em vez de pstatus (como no arquivo).

Obrigado, corrigido no artigo e no arquivo.

 
marketeer писал(а) # :

Qual é o objetivo de definir sua própria variável de tipo em cada uma das classes sucessoras do CShape?

Em princípio, esse membro não é usado em lugar algum, você pode removê-lo. Teoricamente, ele pode ser usado nos descendentes para implementar funções que dependem do tipo de objeto.
 
marketeer писал(а) # :
Eu também gostaria de ouvir alguns esclarecimentos sobre essa questão. Ao mudar do exemplo GetCriticalError_OnDemand para GetCriticalError_Unsafe, toda a mudança foi praticamente reduzida à alteração do tipo do argumento da função de CHello *pobject para CHello &pobject. Ao mesmo tempo, a chamada da função permaneceu inalterada - um ponteiro (CHello *) foi passado para lá. Nesse caso, de acordo com as palavras do autor,"recebemos um erro crítico novamente. A questão é que, se um objeto é passado por referência, o erro crítico ocorre no estágio de chamada de uma função em que um objeto não inicializado é passado para ela". Mas, nesse caso, um ponteiro é passado para a função, não uma referência. A questão é saber de onde ele vem. Você poderia explicar melhor as regras usadas pela MQL5 para a conversão implícita de ponteiros em referências e vice-versa? Ou indicar o local na documentação onde isso está descrito. Se o compilador suportasse tipagem estrita, o exemplo simplesmente não seria compilado porque não há nenhuma função com um argumento do tipo necessário.
Se uma função que aceita um parâmetro como ponteiro estiver explicitamente definida, ela será usada. Se não houver tal função, o ponteiro do objeto será automaticamente convertido em uma referência ao objeto e a função que aceita o objeto por referência será usada.
 
Rosh писал(а) # :
Em princípio, esse membro não é usado em lugar algum, você pode removê-lo. Teoricamente, ele pode ser usado em descendentes para implementar funções que dependem do tipo de objeto.
Entendo corretamente que, de acordo com o código-fonte atual do exemplo, temos um "rake" que, no objeto de uma forma de um tipo específico, há duas variáveis de tipo, por exemplo, CLine::type além de CShape::type? Idealmente, deveria haver uma - da classe base.
 
Rosh писал(а) # :
Se uma função que aceita um parâmetro como ponteiro for explicitamente definida, ela será usada. Se não houver tal função, o ponteiro do objeto será automaticamente convertido em uma referência ao objeto e a função que aceita o objeto por referência será usada.
Há algum lugar onde você possa ler sobre a direção das conversões implícitas relativas a referências e ponteiros? Em particular, a conversão inversa também é feita - de uma referência para um ponteiro?
 
marketeer писал(а) # :
Há algum lugar onde eu possa ler sobre a direção das conversões implícitas realizadas em referências e ponteiros? Em particular, a conversão inversa também é feita - de uma referência para um ponteiro?
Não, para obter um ponteiro de um objeto, useGetPointer().
Документация по MQL5: Общие функции / GetPointer
Документация по MQL5: Общие функции / GetPointer
  • www.mql5.com
Общие функции / GetPointer - Документация по MQL5
 
marketeer писал(а) # :
Entendo corretamente que, de acordo com o código-fonte atual do exemplo, temos um "rake" de que no objeto de uma forma de um tipo específico há duas variáveis de tipo, por exemplo, CLine::type além de CShape::type? O ideal é que haja apenas uma - da classe base.

Sim, você está certo. Há duas variáveis de tipo em cada descendente, como você escreveu. Isso aconteceu porque o código dos descendentes foi copiado. Para tornar um membro da classe base disponível diretamente para os descendentes, ele deve ser definido com o especificador protected ou os métodos públicos get- e set-methods para esse membro devem ser declarados na classe base.

Por exemplo, assim:

//+------------------------------------------------------------------+
//|demo_inheritance.mq5
//| Copyright 2010, MetaQuotes Software Corp.
//|http://www.mql5.com
//+------------------------------------------------------------------+
#property copyright "2010, MetaQuotes Software Corp."
#property link      "http://www.mql5.com"
#property version   "1.00"
//+------------------------------------------------------------------+
//||
//+------------------------------------------------------------------+
class CBase
  {
private:
   int               type;
public:
                     CBase(){type=0;}
   int               GetType(){return(type);}
  };
//+------------------------------------------------------------------+
//||
//+------------------------------------------------------------------+
class CSon: CBase
  {
private:
   int               type;
public:
                     CSon(){type=2;}
   void              PrintType();
  };
//+------------------------------------------------------------------+
//||
//+------------------------------------------------------------------+
void CSon::PrintType()
  {
   Print("CSon.type =",type);
   Print("CBase.type =",CBase::GetType());
  }
//+------------------------------------------------------------------+
//| Função de início do programa de script|
//+------------------------------------------------------------------+
void OnStart()
  {
//---
   CSon  son;
   son.PrintType();
   int father_type=son.GetType();
  }
//+------------------------------------------------------------------+
 
Citação:

"Esse exemplo é muito simples, não é difícil encontrar um erro nele. Mas se o seu programa mql5 contiver centenas ou até milhares de linhas, a detecção desses erros pode se tornar muito mais complicada. Especialmente nos casos em que as condições de situações anormais no comportamento do programa dependem de fatores imprevisíveis - por exemplo, em um determinado mercado."

Como?:-)

 
É quando as especificidades do casal são diferentes de alguma forma.