OOP, modelos e macros em mql5, sutilezas e usos - página 2

 
Ilya Malev:

Já tive muitas situações de declarar campos estáticos em classes que são inicializadas globalmente (antes do OnInit), contanto que você re-clareça o campo estático logo após a descrição da classe, e antes de declarar variável global de sua instância, nunca houve qualquer problema com a inicialização do campo estático (porque neste caso é considerado global e inicializado antes da instância de classe, como eu entendo). Portanto, basta recusar a declaração de variáveis estáticas dentro de métodos e funções e não há problema algum.

Sim, isso mesmo, é inicializada imediatamente nas aulas regulares. Mas não é inicializada nos modelos:

template<typename T>
class A
{
 public: 
  static int a;
};

template<typename T>
int A::a=10;

int f() { return A<int>::a; }

int a= f();

void OnStart()
{
  Print(a); // Результат: 0
};
 
Alexey Viktorov:

Você não pode recusar completamente declarar variáveis estáticas dentro de métodos e funções, mas pelo menos não inicialize outras variáveis estáticas com aqueles métodos ou funções que contêm variáveis estáticas.

Neste exemplo, a princípio a variável estática int b será inicializada, mas a variável estática int f dentro da função int a(int n) ainda não será inicializada e, como resultado, teremos uma algaraviada.

A propósito, sim, é mais um bug. Ou seja, além da inicialização separada de variáveis estáticas/globais, o código inicializa as próprias variáveis estáticas em uma ordem errada. Então você diz "não inicializar outras variáveis estáticas com aqueles métodos ou funções que contêm variáveis estáticas" - como você realmente sugere observar isto? Cada função é independente e existe por si só. Ela tem sua própria implementação, que está sujeita a mudanças. Suponha que não tinha uma variável estática antes, e então você decidiu adicioná-la, o que significa que algo poderia dar errado em algum lugar, porque foi projetado para não ter uma variável estática na função. E como você vai controlar tudo isso?

 
Não entendo este tipo de decisão de desistir disto ou daquilo. Por que desistir? Para quê? Quando você pode resolver o problema e não se negar nada. Bem, cada um tem sua própria escolha...
 
Alexey Navoykov:

A propósito, sim, este é outro bug, ou seja, além da inicialização separada da estática/global remensurada, ela inicializa as próprias variáveis estáticas em ordem errada. Então você diz "não inicializar outras variáveis estáticas com aqueles métodos ou funções que contêm variáveis estáticas" - como você realmente sugere observar isto? Cada função é independente e existe por si só. Ela tem sua própria implementação, que está sujeita a mudanças. Suponha que não tinha uma variável estática antes, e então você decidiu adicioná-la, o que significa que algo poderia dar errado em algum lugar, porque foi projetado para não ter uma variável estática na função. E como você vai controlar tudo isso?

Não é um problema de forma alguma. Basta recusar a inicialização de variáveis por funções e tudo se encaixa no lugar.

int a(int n)
{
 static int f=7;
 return(f+=n);
}

void OnTick()
{
 static int b;
 b=a(9);
}
Vai funcionar bem. Qual é o problema? Uma linha?
 
Alexey Viktorov:

Funcionará para um grito e uma gritaria. Qual é o problema? Uma linha?

Então você entende que a lógica é diferente aqui? Por que declarar b como estático se você atribui um valor a ele em cada chamada?
 
Alexey Navoykov:
Então, você entende que a lógica é diferente aqui? Por que declarar b estática se você atribui um valor a ela em cada chamada?

Eu concordo. Fiz asneira com um pouco de pressa. Mas à variável 'b' pode ser atribuído um valor sob alguma condição e, em vez de 9 valores, pode ser passado para a função dependendo da condição.


Mas em seu exemplo, a variável "a" deve ser inicializada globalmente?

template<typename T>
class A
{
 public: 
  static int a;
};

template<typename T>
int A::a=10;

int f() { return A<int>::a; }

int a= f();

void OnStart()
{
  Print(a); // Результат: 0
};

Não há outra opção no script, e no Expert Advisor você pode declarar a variável no nível global e inicializá-la no OnInit()

É suficiente entender e observar a seqüência de inicialização. Variáveis globais primeiro, depois variáveis estáticas e depois variáveis locais como elas aparecem no código.

Este mesmo exemplo viola a recomendação da documentação de não inicializar variáveis com funções. Foi mais fácil para os desenvolvedores escrever tal aviso do que explicar onde podemos e não podemos fazer isso.

Remova a estática de seu exemplo e obtenha o resultado desejado.

 
Alexey Viktorov:

Mas a variável "a" em sua amostra deve ser inicializada globalmente?

Não necessariamente, mas é mais conveniente para mim. Se é uma constante (e no escopo global as constantes são declaradas principalmente, se o código é inteligente), então não há outra escolha.

Não há outra opção no script, e na EA você pode declarar uma variável globalmente e rubricá-la no OnInit()

É suficiente entender e observar a seqüência de inicialização. Variáveis globais primeiro, depois variáveis estáticas e depois variáveis locais como elas aparecem no código.

Este mesmo exemplo viola a recomendação da documentação de não inicializar variáveis com funções. Foi mais fácil para os desenvolvedores escrever tal aviso do que explicar onde eles podem e não podem.

Remova a estática de seu exemplo e obtenha o resultado desejado.

Com relação a tudo em amarelo, tenho uma pergunta: Por quê? Eu já descobri como resolver o problema.
 
Atualizou o arquivo na página anterior. Corrigida uma pequena falha.
 
Alexey Navoykov:

Não necessariamente, mas é mais conveniente para mim. Se é uma constante (e a visibilidade global declara em sua maioria constantes, se o código é inteligente), não há outra escolha.

Com relação a tudo em amarelo, tenho uma pergunta: Por quê? Eu já descobri como resolver o problema.

Você encontrou uma maneira de criá-lo.

 
Alexey Navoykov:

Sim, isso mesmo, em classes regulares é inicializada imediatamente. Mas em classes de modelos não é:

Você está tentando usar um campo estático deuma classe na fase de inicialização antes de pelo menos 1 instância dessa classe ter sido criada. Na minha opinião, isto é uma perversão... É assim que funciona normalmente:

template<typename T>
class A
{
 public: 
  A(){}
  static int a;
  int f(){return a;}
};

template<typename T>
int A::a=10;

A<int> _a;


int a= _a.f();

void OnStart()
{
  Print(a);
};
O princípio do encapsulamento em geral sugere que tais campos devem ser ocultos e não públicos.