Ponteiros de Objeto
Em MQL5, é possível criar dinamicamente objetos de tipo complexo. Isso é feito usando o operador new, que retorna um identificador para o objeto criado. O descritor tem um tamanho de 8 bytes. Sintaticamente, os descritores de objetos em MQL5 são semelhantes a ponteiros em C++.
Exemplo:
MyObject* hobject= new MyObject();
|
Ao contrário do C++, a variável hobject do exemplo acima não é um ponteiro para a memória, senão um descritor para um objeto. Além disso, na linguagem MQL5, todos os objetos nos parâmetros da função devem ser passados por referência. Exemplos de passagem de objetos como parâmetro de função:
class Foo
{
public:
string m_name;
int m_id;
static int s_counter;
//--- construtores e destruidores
Foo(void){Setup("noname");};
Foo(string name){Setup(name);};
~Foo(void){};
//--- inicializamos o objeto Foo
void Setup(string name)
{
m_name=name;
s_counter++;
m_id=s_counter;
}
};
int Foo::s_counter=0;
//+------------------------------------------------------------------+
//| Script program start function |
//+------------------------------------------------------------------+
void OnStart()
{
//--- declaramos o objeto como uma variável com criação automática
Foo foo1;
//--- variante de passagem de objeto por referência
PrintObject(foo1);
//--- declaramos um ponteiro para um objeto e o criamos usando o operador 'new'
Foo *foo2=new Foo("foo2");
//--- variante de passagem de um ponteiro para um objeto por referência
PrintObject(foo2); // o ponteiro para o objeto é convertido automaticamente pelo compilador
//--- declaramos um array de objetos Foo
Foo foo_objects[5];
//--- variante de passagem de array de objetos
PrintObjectsArray(foo_objects); // função separada para passagem de array de objetos
//--- declaramos um array de ponteiros para objetos do tipo Foo
Foo *foo_pointers[5];
for(int i=0;i<5;i++)
foo_pointers[i]=new Foo("foo_pointer");
//--- variante de passagem de array de ponteiros
PrintPointersArray(foo_pointers); // função separada para passagem de array de ponteiros
//--- antes de concluir o trabalho, sempre devemos excluir os objetos criados como ponteiros
delete(foo2);
//--- removemos o array de ponteiros
int size=ArraySize(foo_pointers);
for(int i=0;i<5;i++)
delete(foo_pointers[i]);
//---
}
//+------------------------------------------------------------------+
//| Os objetos são sempre passados por referência |
//+------------------------------------------------------------------+
void PrintObject(Foo &object)
{
Print(__FUNCTION__,": ",object.m_id," Object name=",object.m_name);
}
//+------------------------------------------------------------------+
//| Passagem de um array de objetos |
//+------------------------------------------------------------------+
void PrintObjectsArray(Foo &objects[])
{
int size=ArraySize(objects);
for(int i=0;i<size;i++)
PrintObject(objects[i]);
}
//+------------------------------------------------------------------+
//| Passagem de array de ponteiros para um objeto |
//+------------------------------------------------------------------+
void PrintPointersArray(Foo* &objects[])
{
int size=ArraySize(objects);
for(int i=0;i<size;i++)
PrintObject(objects[i]);
}
//+------------------------------------------------------------------+
|
Verificação do ponteiro antes de seu uso
A tentativa de acesso a um ponteiro inválido causa o encerramento crítico do programa. Para verificar o ponteiro antes de usá-lo, usamos a função CheckPointer. O ponteiro pode ser inválido quando:
- o ponteiro é NULL;
- o objeto foi destruído usando o operador delete.
Esta função pode ser usada como verificação de ponteiro. Um valor diferente de zero garante que os dados possam ser acessados com base nesse ponteiro.
class CMyObject
{
protected:
double m_value;
public:
CMyObject(void);
CMyObject(double value) {m_value=value;};
~CMyObject(void){};
//---
double Value(void) {return(m_value);}
};
//+------------------------------------------------------------------+
//| Script program start function |
//+------------------------------------------------------------------+
void OnStart()
{
//--- criamos um objeto não inicializado
CMyObject *pointer;
if(CheckPointer(pointer)==POINTER_INVALID)
Print("1. pointer is ", EnumToString(CheckPointer(pointer)));
else
Print("1. pointer.Value()=", pointer.Value());
//--- inicializamos o ponteiro
pointer=new CMyObject(M_PI);
if(CheckPointer(pointer)==POINTER_INVALID)
Print("2. pointer is ", EnumToString(CheckPointer(pointer)));
else
Print("2. pointer.Value()=", pointer.Value());
//--- excluimos o objeto
delete(pointer);
if(CheckPointer(pointer)==POINTER_INVALID)
Print("3. pointer is ", EnumToString(CheckPointer(pointer)));
else
Print("3. pointer.Value()=", pointer.Value());
}
/*
1. pointer is POINTER_INVALID
2. pointer.Value()=3.141592653589793
3. pointer is POINTER_INVALID
*/
|
Para verificação rápida do ponteiro, você também pode usar o operador "!" (LNOT) que testa sua validade por meio de uma chamada de função implícita CheckPointer. Isso permite que você escreva o código de forma mais concisa e clara. Veja como seriam as verificações do exemplo anterior:
//+------------------------------------------------------------------+
//| Script program start function |
//+------------------------------------------------------------------+
void OnStart()
{
//--- criamos um objeto não inicializado
CMyObject *pointer;
if(!pointer)
Print("1. pointer is ", EnumToString(CheckPointer(pointer)));
else
Print("1. pointer.Value()=", pointer.Value());
//--- inicializamos o ponteiro
pointer=new CMyObject(M_PI);
if(!pointer)
Print("2. pointer is ", EnumToString(CheckPointer(pointer)));
else
Print("2. pointer.Value()=", pointer.Value());
//--- excluimos o objeto
delete(pointer);
if(!pointer)
Print("3. pointer is ", EnumToString(CheckPointer(pointer)));
else
Print("3. pointer.Value()=", pointer.Value());
}
/*
1. pointer is POINTER_INVALID
2. pointer.Value()=3.141592653589793
3. pointer is POINTER_INVALID
*/
|
Para uma verificação rápida de NULL, use o operador "==". Por exemplo: ptr==NULL ou ptr!=NULL.
Também Veja
Variáveis, Inicialização de Variáveis, Visibilidade Escopo e Tempo de Vida de Variáveis, Criando e Excluindo Objetos