OOP, templates et macros dans mql5, subtilités et utilisations - page 2

 
Ilya Malev:

J'ai eu de nombreuses situations de déclaration de champs statiques dans des classes qui sont initialisées globalement (avant OnInit), tant que vous redéclarez le champ statique juste après la description de la classe, et avant de déclarer la variable globale de son instance, il n'y a jamais eu de problème avec l'initialisation du champ statique (parce que dans ce cas il est considéré comme global et initialisé avant l'instance de la classe comme je le comprends). Il suffit donc de refuser de déclarer les variables statiques à l'intérieur des méthodes et des fonctions et il n'y a aucun problème.

Oui, c'est vrai, il est initialisé tout de suite dans les classes normales. Mais il n'est pas initialisé dans les modèles :

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:

Vous ne pouvez pas refuser complètement de déclarer des variables statiques à l'intérieur des méthodes et des fonctions, mais au moins ne pas initialiser d'autres variables statiques avec ces méthodes ou fonctions qui contiennent des variables statiques.

Dans cet exemple, la variable static int b sera d'abord initialisée mais la variable static int f dans la fonction int a(int n) ne sera pas encore initialisée et nous obtiendrons du charabia.

Au fait, oui, il s'agit d'un bug supplémentaire, c'est-à-dire qu'en plus de l'initialisation séparée des variables statiques/globales, le code initialise les variables statiques elles-mêmes dans un ordre incorrect. Vous dites donc "ne pas initialiser d'autres variables statiques avec ces méthodes ou fonctions qui contiennent des variables statiques" - comment suggérez-vous concrètement d'observer cela ? Chaque fonction est indépendante et existe par elle-même. Il dispose de sa propre mise en œuvre, qui est susceptible d'être modifiée. Supposons qu'il n'y avait pas de variable statique auparavant, et que vous décidiez de l'ajouter, ce qui signifie que quelque chose pourrait mal tourner quelque part, car il a été conçu pour ne pas avoir de variable statique dans la fonction. Et comment allez-vous contrôler tout cela ?

 
Je ne comprends pas ce genre de décision d'abandonner ceci ou cela. Pourquoi abandonner ? Pour quoi faire ? Quand on peut résoudre le problème et ne rien se refuser. Enfin, chacun a son propre choix...
 
Alexey Navoykov:

Au fait, oui, c'est un autre bug, c'est-à-dire qu'en plus de l'initialisation séparée de la remesure statique/globale, il initialise les variables statiques elles-mêmes dans le mauvais ordre. Vous dites donc "ne pas initialiser d'autres variables statiques avec ces méthodes ou fonctions qui contiennent des variables statiques" - comment suggérez-vous concrètement d'observer cela ? Chaque fonction est indépendante et existe par elle-même. Il possède sa propre mise en œuvre, qui est susceptible d'être modifiée. Supposons qu'il n'y avait pas de variable statique auparavant, et que vous décidiez de l'ajouter, ce qui signifie que quelque chose pourrait mal tourner quelque part, car il a été conçu pour ne pas avoir de variable statique dans la fonction. Et comment allez-vous contrôler tout cela ?

Ce n'est pas un problème du tout. Il suffit de refuser l'initialisation des variables par les fonctions et tout se met en place.

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

void OnTick()
{
 static int b;
 b=a(9);
}
Cela fonctionnera très bien. Quel est le problème ? Une ligne ?
 
Alexey Viktorov:

Ca marchera pour un hoot et un holler. Quel est le problème ? Une ligne ?

Vous comprenez donc que la logique est différente ici ? Pourquoi déclarer b comme statique si vous lui attribuez une valeur à chaque appel ?
 
Alexey Navoykov:
Vous comprenez donc que la logique est différente ici ? Pourquoi déclarer b static si vous lui attribuez une valeur à chaque appel ?

Je suis d'accord. J'ai fait un peu n'importe quoi dans la précipitation. Mais la variable 'b' peut se voir attribuer une valeur sous certaines conditions et, au lieu de 9, des valeurs peuvent être passées dans la fonction en fonction de la condition.


Mais dans votre exemple, la variable 'a' doit-elle être initialisée globalement ?

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
};

Il n'y a pas d'autre option dans le script, et dans le Conseiller Expert vous pouvez déclarer la variable au niveau global et l'initialiser dans OnInit()

Il suffit de comprendre et d'observer la séquence d'initialisation. Les variables globales d'abord, puis les variables statiques et enfin les variables locales au fur et à mesure de leur apparition dans le code.

Cet exemple même viole la recommandation de la documentation de ne pas initialiser les variables avec des fonctions. Il était plus facile pour les développeurs d'écrire un tel avertissement que d'expliquer où ils peuvent et ne peuvent pas le faire.

Supprimez les éléments statiques de votre exemple et obtenez le résultat souhaité.

 
Alexey Viktorov:

Mais la variable 'a' de votre échantillon doit-elle être initialisée globalement ?

Pas nécessairement, mais c'est plus pratique pour moi. Si c'est une constante (et les constantes visibles globalement sont déclarées la plupart du temps, si le code est intelligent), alors il n'y a pas d'autre choix.

Il n'y a pas d'autre option dans le script, et dans l'EA vous pouvez déclarer une variable globalement et l'initialiser dans OnInit()

Ilsuffit de comprendre et d'observer la séquence d'initialisation. Les variables globales d'abord, puis les variables statiques et enfin les variables locales au fur et à mesure qu'elles apparaissent dans le code.

Cet exemple même viole la recommandation de la documentation de ne pas initialiser les variables avec des fonctions. Il était plus facile pour les développeurs d'écrire un tel avertissement que d'expliquer où ils peuvent et ne peuvent pas le faire.

Retirez les statiques de votre exemple et obtenez le résultat souhaité.

Concernant tout ce qui est en jaune, j'ai une question : POURQUOI ? J'ai déjà trouvé comment résoudre le problème.
 
Mise à jour du fichier de la page précédente. Correction d'un défaut mineur.
 
Alexey Navoykov:

Pas nécessairement, mais c'est plus pratique pour moi. Si c'est une constante (et la visibilité globale déclare le plus souvent des constantes, si le code est intelligent), il n'y a pas d'autre choix.

Concernant tout ce qui est en jaune, j'ai une question : POURQUOI ? J'ai déjà trouvé comment résoudre le problème.

Vous avez trouvé un moyen de le créer.

 
Alexey Navoykov:

Oui, c'est vrai, dans les classes normales, il est initialisé immédiatement. Mais dans les classes de modèles, ce n'est pas le cas :

Vous essayez d'utiliser un champ statiqued'une classe à l'étape d'initialisation avant qu'au moins une instance de cette classe ait été créée. A mon avis, c'est une perversion... C'est ainsi que cela fonctionne normalement :

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);
};
Le principe d'encapsulation en général suggère que de tels champs devraient être cachés plutôt que publics.
Raison: