Punteros a objetos
En MQL5, es posible crear dinámicamente objetos de tipo complejo. Esto se hace usando el operador new,que retorna el descriptor del objeto creado. El descriptor tiene un tamaño de 8 bytes. Sintácticamente, los descriptores de los objetos en MQL5 son similares a los punteros en C++.
Ejemplo:
MyObject* hobject= new MyObject();
|
A diferencia de C++, la variable hobject en el ejemplo anterior no es un puntero de memoria, sino un descriptor de objeto. Además, en MQL5, todos los objetos de los parámetros de las funciones deben transmitirse por referencia. Ejemplos de transmisión de objetos como parámetros de funciones:
class Foo
{
public::
string m_name;
int m_id;
static int s_counter;
//--- constructores y destructores
Foo(void){Setup("noname");};
Foo(string name){Setup(name);};
~Foo(void){};
//--- inicializamos el 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 el objeto como una variable con creación automática
Foo foo1;
//--- variante de transmisión de un objeto por referencia
PrintObject(foo1);
//--- declaramos un puntero a un objeto y lo creamos con el operador 'new'
Foo *foo2=new Foo("foo2");
//--- variante de transmisión de un puntero a un objeto por referencia
PrintObject(foo2); // el puntero a un objeto es convertido automáticamente por el compilador
//--- declaramos un array de objetos Foo
Foo foo_objects[5];
//--- variante de transmisión de un array de objetos
PrintObjectsArray(foo_objects); // función separada para pasar un array de objetos
//--- declaramos un array de punteros a los objetos Foo
Foo *foo_pointers[5];
for(int i=0;i<5;i++)
foo_pointers[i]=new Foo("foo_pointer");
//--- variante de transmisión de un array de objetos
PrintPointersArray(foo_pointers); // función aparte para transmitir un array de objetos
//--- antes de completar el trabajo, nos aseguramos de borrar los objetos creados como punteros
delete(foo2);
//--- borramos el array de punteros
int size=ArraySize(foo_pointers);
for(int i=0;i<5;i++)
delete(foo_pointers[i]);
//---
}
//+------------------------------------------------------------------+
//| Los objetos siempre se transmiten por referencia |
//+------------------------------------------------------------------+
void PrintObject(Foo &object)
{
Print(__FUNCTION__,": ",object.m_id," Object name=",object.m_name);
}
//+------------------------------------------------------------------+
//| Transmisión de un array de objetos |
//+------------------------------------------------------------------+
void PrintObjectsArray(Foo &objects[])
{
int size=ArraySize(objects);
for(int i=0;i<size;i++)
PrintObject(objects[i]);
}
//+------------------------------------------------------------------+
//| Transmisión de un array de punteros de objeto |
//+------------------------------------------------------------------+
void PrintPointersArray(Foo* &objects[])
{
int size=ArraySize(objects);
for(int i=0;i<size;i++)
PrintObject(objects[i]);
}
//+------------------------------------------------------------------+
|
Comprobación del puntero antes de su uso
El intenta de acceso a un puntero no válido provoca la finalización crítica del programa. Para comprobar un puntero antes de usarlo, utilice la función CheckPointer. El puntero puede no ser válido en los siguientes casos:
- el puntero es igual a NULL;
- el objeto ha sido destruido por el operador delete.
Esta función se puede usar como comprobación de la corrección de un puntero. Un valor distinto a cero asegura que se pueda acceder a los datos usando este puntero.
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()
{
//--- creamos un objeto no inicializado
CMyObject *pointer;
if(CheckPointer(pointer)==POINTER_INVALID)
Print("1. pointer is ", EnumToString(CheckPointer(pointer)));
else
Print("1. pointer.Value()=", pointer.Value());
//--- inicializamos el puntero
pointer=new CMyObject(M_PI);
if(CheckPointer(pointer)==POINTER_INVALID)
Print("2. pointer is ", EnumToString(CheckPointer(pointer)));
else
Print("2. pointer.Value()=", pointer.Value());
//--- eliminamos el 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
*/
|
También podemos usar el operador "!" ( para comprobar rápidamente el punteroLNOT), que comprueba su validez usando una llamada implícita a la función CheckPointer. Esto nos permite escribir el código de forma más concisa y clara. Este es el aspecto que tendrían las comprobaciones del ejemplo anterior:
//+------------------------------------------------------------------+
//| Script program start function |
//+------------------------------------------------------------------+
void OnStart()
{
//--- creamos un objeto no inicializado
CMyObject *pointer;
if(!pointer)
Print("1. pointer is ", EnumToString(CheckPointer(pointer)));
else
Print("1. pointer.Value()=", pointer.Value());
//--- inicializamos el puntero
pointer=new CMyObject(M_PI);
if(!pointer)
Print("2. pointer is ", EnumToString(CheckPointer(pointer)));
else
Print("2. pointer.Value()=", pointer.Value());
//--- eliminamos el 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 comprobar rápidamente la existencia de NULL, usamos el operador "==". Por ejemplo: ptr==NULL o ptr!=NULL.
Véase también
Variables, Inicialización de variables, Visibilidad y tiempo de vida de variables, Creación y eliminación de objetos