Definición de estructuras
Una estructura consta de variables; estas pueden ser integradas o de otros tipos definidos por el usuario. El propósito de la estructura es combinar datos relacionados lógicamente en un único contenedor. Supongamos que tenemos una función que realiza un cálculo determinado y acepta un conjunto de parámetros: número de barras que muestran un historial de cotizaciones para su análisis, fecha en que se inició el análisis, tipo de precio y número de señales asignadas (por ejemplo, armónicas).
double calculate(datetime start, int barNumber,
|
En realidad, puede haber más parámetros y no será fácil pasarlos a la función como una lista. Además, basándose en los resultados de varios cálculos, tiene sentido guardar algunos de los mejores ajustes en algún tipo de array. Por lo tanto, es conveniente representar un conjunto de parámetros como un único objeto.
La descripción de la estructura con las mismas variables tiene el siguiente aspecto:
struct Settings
|
La descripción comienza con la palabra clave struct seguida del identificador que elijamos. A continuación aparece un bloque de código entre llaves, dentro del cual se describen las variables incluidas en la estructura que se denominan también campos o miembros de una estructura. Hay un punto y coma después de las llaves, ya que toda la notación es una sentencia que define un nuevo tipo y al final de las mismas es necesario escribir ';'.
Una vez definido el tipo, podemos aplicarlo del mismo modo que los tipos integrados. En concreto, el nuevo tipo permite describir la variable Settings en el programa de la forma habitual.
Settings s; |
Es importante señalar que una única descripción de estructura permite crear un número arbitrario de variables de estructura e incluso arrays de este tipo. Cada instancia de estructura tendrá su propio conjunto de elementos, y estos contendrán valores independientes.
Para acceder a los miembros de una estructura se proporciona un operador de desreferenciación especial: el carácter de punto '.'. A la izquierda debe haber una variable de tipo estructura, y a la derecha, un identificador de uno de los campos disponibles en la misma. A continuación se explica cómo asignar un valor a un elemento de la estructura:
void OnStart()
|
Hay una forma más cómoda de rellenar la estructura: la inicialización agregada. En este caso, el signo '=' se escribe a la derecha de la variable de estructura, seguido de una lista, separada por comas, con los valores iniciales de todos los campos entre llaves.
Settings s = {D'2021.01.01', 1000, PRICE_CLOSE, 8}; |
Los tipos del valor deben coincidir con los tipos del elemento correspondiente. Se permite especificar menos valores que el número de campos: los campos restantes recibirán entonces valores cero.
Tenga en cuenta que este método sólo funciona cuando la variable está inicializada, en el momento de su definición. Es imposible asignar de esta forma el contenido de una estructura ya existente: obtendremos un error de compilación.
Settings s;
|
Utilizando el operador de desreferenciación puede leer también el valor de un elemento de la estructura. Por ejemplo, utilizamos el número de barras para calcular el número de componentes.
s.components = (int)(MathSqrt(s.barNumber) + 1); |
Aquí MathSqrt es la función raíz cuadrada integrada.
Hemos introducido un nuevo tipo, Settings, para facilitar el paso de un conjunto de parámetros a una función. Ahora puede utilizarse como único parámetro de la función actualizada calculate:
double calculate(Settings &settings); |
Fíjese en el ampersand '&' delante del nombre del parámetro, que significa pasar por referencia. Las estructuras sólo pueden pasarse como parámetros por referencia.
Las estructuras también son útiles si necesita devolver un conjunto de valores de una función en lugar de un único valor. Imaginemos que la función calculate debe devolver, no un valor del tipo double, sino varios coeficientes y algunas recomendaciones de trading (dirección de la operación de trading y probabilidad de éxito). Entonces, podemos definir el tipo de la estructura Result y utilizarlo en el prototipo de la función (Structs.mq5).
struct Result
|
Las llaves vacías de la línea Result r = {} representan el inicializador agregado mínimo: rellena todos los campos de la estructura con ceros.
La definición y la declaración del tipo de estructura pueden hacerse por separado, si es necesario (por regla general, la declaración va en el archivo mqh de encabezado, y la definición, en el archivo mq5). Esta sintaxis ampliada se abordará en la sección Capítulo sobre las clases.