Estruturas
Uma estrutura é um conjunto de elementos de qualquer tipo (exceto o tipo void). Portanto, a estrutura combina dados logicamente relacionados de diferentes tipos.
Declaração da Estrutura
O tipo de dados estrutura é determinado pela seguinte descrição:
struct structure_name
{
elements_description
};
O nome da estrutura não pode ser usado como um identificador (nome de uma variável ou função). Deve-se notar que em estruturas MQL5, os elementos seguem um ao outro diretamente, sem alinhamento. Em C++ tal ordem é feita pelo compilador usando a seguinte instrução:
#pragma pack(1)
Se você quiser ter outro alinhamento na estrutura, use membros auxiliares, "fillers" (preenchedores) para o tamanho certo.
Exemplo:
struct trade_settings
{
uchar slippage; // valor do tamanho do slippage admissível - 1 byte
char reserved1; // pula 1 byte
short reserved2; // pula 2 bytes
int reserved4; // outros 4 bytes são pulados. garantir um alinhamento de 8 bytes de limite
double take; // valores do preço de fixação de lucro
double stop; // valor do preço de stop de proteção
};
Tal descrição de estruturas alinhadas é necessário somente para transferência de dados para funções de dll importadas.
Atenção: Este exemplo ilustra dados incorretamente esquematizados. Seria melhor primeiro declarar o take e stop de grandes volumes de dados do tipo double, e então declarar o membro slippage do tipo uchar. Neste caso, a representação interna de dados será sempre a mesma, independentemente do valor especificado no #pragma pack().
Se a estrutura contém variáveis do tipo string e/ou objeto de um array dinâmico, o compilador atribui um construtor implícito para tal estrutura. Este construtor redefine todos os membros de tipo string da estrutura e corretamente inicializa objetos do array dinâmico.
Estruturas Simples
As estruturas contendo cadeias de caracteres, objetos de classe, ponteiros e objetos de matrizes dinâmicas são chamadas de estruturas simples. As variáveis de estruturas simples e suas matrizes podem ser transferidas como parâmetros para as funções importadas a partir de DLL.
Copiar e colar estruturas simples é permitido apenas em dois casos:
se os objetos pertencem ao mesmo tipo de estrutura
se os objetos são ligados por uma linha herança, isto é, uma estrutura é um descendente de uma outra estrutura.
Mostraremos isso com ajuda de exemplos, criamos uma estrutura personalizada CustomMqlTick idêntica em composição à estrutura construída MqlTick. O compilador não permitirá tentativas de copiar e colar os valores do objeto MqlTick no objeto de tipo CustomMqlTick. A conversão direta para o tipo desejado também causará um erro de compilação:
//--- copiar estruturas simples de diferentes tipos é restrito
my_tick1=last_tick; // aqui o compilador gerará um erro
//--- combinar estruturas de diferente tipo também é restrito
my_tick1=(CustomMqlTick)last_tick;// aqui o compilador gerará um erro
Portanto, resta só uma opção, isto é, copiar e colar os valores dos membros da estrutura elemento por elemento. Mas, ao fazer isto, é permitido copiar e colar os valores dos objetos do mesmo tipo CustomMqlTick.
CustomMqlTick my_tick1,my_tick2;
//--- também é possível copiar e colar objetos da mesma estrutura CustomMqlTick
my_tick2=my_tick1;
//--- criamos uma matriz a partir de objetos da estrutura simples CustomMqlTick e registramos nela os valores
CustomMqlTick arr[2];
arr[0]=my_tick1;
arr[1]=my_tick2;
Como um teste é chamada a função ArrayPrint() para exibir os valores da matriz arr[], no diário.
//+------------------------------------------------------------------+
//| Script program start function |
//+------------------------------------------------------------------+
void OnStart()
{
//--- criamos a mesma estrutura como a construída por MqlTick
struct CustomMqlTick
{
datetime time; // Tempo da última atualização dos preços
double bid; // Preço atual Bid
double ask; // Preço atual Ask
double last; // Preço atual da última transação (Last)
ulong volume; // Volume para o preço atual Last
long time_msc; // Hora da última atualização dos preços em milissegundos
uint flags; // Sinalizadores de ticks
};
//--- obtemos os valores do último ticks
MqlTick last_tick;
CustomMqlTick my_tick1,my_tick2;
//--- tentamos colar e copiar os dados a partir do MqlTick no CustomMqlTick
if(SymbolInfoTick(Symbol(),last_tick))
{
//--- copiar e colar estruturas simples não aparentadas é restrito
//1. my_tick1=last_tick; // aqui o compilador gerará um erro
//--- combinar estruturas não aparentadas também é restrito
//2. my_tick1=(CustomMqlTick)last_tick;// aqui o compilador gerará um erro
//--- por isso copiamos e colamos os membros da estrutura elemento por elemento
my_tick1.time=last_tick.time;
my_tick1.bid=last_tick.bid;
my_tick1.ask=last_tick.ask;
my_tick1.volume=last_tick.volume;
my_tick1.time_msc=last_tick.time_msc;
my_tick1.flags=last_tick.flags;
//--- também é possível copiar e colar objetos da mesma estrutura CustomMqlTick
my_tick2=my_tick1;
//--- criamos uma matriz a partir de objetos da estrutura simples CustomMqlTick e registramos nela os valores
CustomMqlTick arr[2];
arr[0]=my_tick1;
arr[1]=my_tick2;
ArrayPrint(arr);
//--- exemplo de exibição de valores de matriz contendo objetos do tipo CustomMqlTick
/*
[time] [bid] [ask] [last] [volume] [time_msc] [flags]
[0] 2017.05.29 15:04:37 1.11854 1.11863 +0.00000 1450000 1496070277157 2
[1] 2017.05.29 15:04:37 1.11854 1.11863 +0.00000 1450000 1496070277157 2
*/
}
else
Print("SymbolInfoTick() failed, error = ",GetLastError());
}
O segundo exemplo mostra a possibilidade de copiar e colar estruturas simples segundo linha de herança. Assumamos que temos uma estrutura básica Animal, da qual são geradas - para herança - as estruturas Cat e Dog. Nós podemos copiar e colar entre si mesmos os objetos Animal e Cat (ou Animal e Dog), no entanto não podemos copiar e colar entre sim mesmos Cat e Dog, embora ambos sejam descendentes da estrutura Animal.
//--- estrutura para descrever cães
struct Dog: Animal
{
bool hunting; // raça de caça
};
//--- estrutura para descrição de gatos
struct Cat: Animal
{
bool home; // raça domestica
};
//--- criamos os objetos das subclasses
Dog dog;
Cat cat;
//--- é possível copiar no ancestral e colar no descendente (Animal ==> Dog)
dog=some_animal;
dog.swim=true; // cães sabem nadar
//--- é impossível copiar e colar objetos de subestruturas (Dog != Cat)
cat=dog; // aqui o compilador gerará um erro
Código completo de exemplo:
//--- estrutura básica para descrever animais
struct Animal
{
int head; // número de cabeças
int legs; // número de patas
int wings; // número de assas
bool tail; // presença de cauda
bool fly; // voa
bool swim; // nada
bool run; // corre
};
//--- estrutura para descrever cães
struct Dog: Animal
{
bool hunting; // raça de caça
};
//--- estrutura para descrição de gatos
struct Cat: Animal
{
bool home; // raça domestica
};
//+------------------------------------------------------------------+
//| Script program start function |
//+------------------------------------------------------------------+
void OnStart()
{
//--- criamos um objeto do tipo básico Animal e descrevemo-lo
Animal some_animal;
some_animal.head=1;
some_animal.legs=4;
some_animal.wings=0;
some_animal.tail=true;
some_animal.fly=false;
some_animal.swim=false;
some_animal.run=true;
//--- criamos os objetos dos subtipos
Dog dog;
Cat cat;
//--- é possível copiar no ancestral e colar no descendente (Animal ==> Dog)
dog=some_animal;
dog.swim=true; // cães sabem nadar
//--- é impossível copiar e colar objetos de subestruturas (Dog != Cat)
//cat=dog; // aqui o compilador gerará um erro
//--- por isso é possível copiar e colar apenas elemento por elemento
cat.head=dog.head;
cat.legs=dog.legs;
cat.wings=dog.wings;
cat.tail=dog.tail;
cat.fly=dog.fly;
cat.swim=false; // gatos não sabem nadar
//--- é possível copiar valores no descendente e colá-los no ancestral
Animal elephant;
elephant=cat;
elephant.run=false;// elefantes não sabem correr
elephant.swim=true;// elefantes nadam
//--- criamos uma matriz
Animal animals[4];
animals[0]=some_animal;
animals[1]=dog;
animals[2]=cat;
animals[3]=elephant;
//--- imprimimos
ArrayPrint(animals);
//--- resultado da execução
/*
[head] [legs] [wings] [tail] [fly] [swim] [run]
[0] 1 4 0 true false false true
[1] 1 4 0 true false true true
[2] 1 4 0 true false false false
[3] 1 4 0 true false true false
*/
}
Outro método para copiar e colar tipos simples consiste em utilizar associações, para fazer isto, os objetos destas estruturas devem ser membros da mesma associação — veja o exemplo em union.
Acesso a Membros de Estrutura
A estrutura é um novo tipo de dados permitindo declarar variáveis deste tipo. A estrutura pode ser declarado somente um vez dentro de um projeto. Os membros de estrutura são acessados usando aoperação ponto (.).
Exemplo:
struct trade_settings
{
double take; // valor do preço de fixação do lucro
double stop; // valor do preço stop de proteção
uchar slippage; // valor do slippage admissível
};
//--- cria e inicializa uma variável do tipo trade_settings
trade_settings my_set={0.0,0.0,5};
if (input_TP>0) my_set.take=input_TP;
Modificador final
A presença do modificador final, ao declarar a estrutura, proíbe a herança a partir dela. Se a estrutura não precisar de alterações futuras ou se essas alterações não se puderem levar a cabo por causa de questões de segurança, declare-a usando o modificador final. Além disso, todos os membros da estrutura também serão implicitamente considerados como final.
struct settings final
{
//--- corpo da estrutura
};
struct trade_settings : public settings
{
//--- corpo da estrutura
};
Como no exemplo acima, ao tentar herdar a partir da estrutura, usando o modificador final, o compilador irá emitir um erro:
cannot inherit from 'settings' as it has been declared as 'final'
see declaration of 'settings'