OOP, Vorlagen und Makros in mql5, Feinheiten und Anwendungen - Seite 2

 
Ilya Malev:

Ich habe viele Situationen der Deklaration von statischen Feldern in Klassen, die global (vor OnInit) initialisiert werden, solange Sie statische Feld direkt nach Klassenbeschreibung und vor der Deklaration der globalen Variable seiner Instanz neu deklarieren, gab es nie ein Problem mit statischen Feldinitialisierung (weil in diesem Fall es als global und initialisiert vor der Klasse Instanz, wie ich verstehe). Sie müssen also nur darauf verzichten, statische Variablen innerhalb von Methoden und Funktionen zu deklarieren, und schon gibt es kein Problem mehr.

Ja, das ist richtig, in regulären Klassen wird sie sofort initialisiert. Aber es ist nicht in Vorlagen initialisiert:

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:

Sie können sich nicht völlig weigern, statische Variablen innerhalb von Methoden und Funktionen zu deklarieren, aber Sie sollten zumindest keine anderen statischen Variablen mit den Methoden oder Funktionen initialisieren, die statische Variablen enthalten.

In diesem Beispiel wird zunächst die statische Variable int b initialisiert, aber die statische Variable int f innerhalb der Funktion int a(int n) wird noch nicht initialisiert, und als Ergebnis erhalten wir Kauderwelsch.

Übrigens, ja, es ist ein weiterer Fehler, d.h. neben der getrennten Initialisierung von statischen/globalen Variablen, initialisiert der Code die statischen Variablen selbst in einer falschen Reihenfolge. Sie sagen also: "Initialisieren Sie keine anderen statischen Variablen mit den Methoden oder Funktionen, die statische Variablen enthalten" - wie schlagen Sie eigentlich vor, dies zu beachten? Jede Funktion ist unabhängig und existiert für sich selbst. Sie hat ihre eigene Umsetzung, die sich noch ändern kann. Angenommen, es gab vorher keine statische Variable, und Sie haben beschlossen, sie hinzuzufügen, was bedeutet, dass irgendwo etwas schief gehen könnte, weil die Funktion nicht für eine statische Variable ausgelegt war. Und wie wollen Sie das alles kontrollieren?

 
Ich verstehe diese Art von Entscheidung, dieses oder jenes aufzugeben, nicht. Warum aufgeben? Wozu? Wenn man das Problem lösen kann und sich nichts vorenthalten muss. Nun, jeder hat seine eigene Wahl...
 
Alexey Navoykov:

Übrigens, ja, das ist ein weiterer Fehler, d.h. neben der getrennten Initialisierung von statischen/globalen remeasured, initialisiert es statische Variablen selbst in falscher Reihenfolge. Sie sagen also: "Initialisieren Sie keine anderen statischen Variablen mit den Methoden oder Funktionen, die statische Variablen enthalten" - wie schlagen Sie eigentlich vor, dies zu beachten? Jede Funktion ist unabhängig und existiert für sich selbst. Sie hat ihre eigene Umsetzung, die sich noch ändern kann. Angenommen, es gab vorher keine statische Variable, und Sie haben beschlossen, sie hinzuzufügen, was bedeutet, dass irgendwo etwas schief gehen könnte, weil die Funktion nicht für eine statische Variable ausgelegt war. Und wie wollen Sie das alles kontrollieren?

Das ist überhaupt kein Problem. Es genügt, die Initialisierung von Variablen durch Funktionen zu verweigern, und alles wird sich fügen.

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

void OnTick()
{
 static int b;
 b=a(9);
}
Es wird gut funktionieren. Wo liegt das Problem? Eine Zeile?
 
Alexey Viktorov:

Für einen Hupf und einen Schrei wird es funktionieren. Wo liegt das Problem? Eine Zeile?

Verstehen Sie also, dass die Logik hier anders ist? Warum b als statisch deklarieren, wenn Sie ihm bei jedem Aufruf einen Wert zuweisen?
 
Alexey Navoykov:
Verstehen Sie also, dass die Logik hier anders ist? Warum b überhaupt als statisch deklarieren, wenn Sie ihm bei jedem Aufruf einen Wert zuweisen?

Ich stimme zu. Ich habe in der Eile ein bisschen Mist gebaut. Der Variablen "b" kann jedoch unter einer bestimmten Bedingung ein Wert zugewiesen werden, und anstelle von 9 Werten können je nach der Bedingung Werte an die Funktion übergeben werden.


Aber in Ihrem Beispiel muss die Variable "a" global initialisiert werden?

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

Im Skript gibt es keine andere Option, und im Expert Advisor können Sie die Variable auf globaler Ebene deklarieren und sie in OnInit() initialisieren

Es genügt, die Initialisierungssequenz zu verstehen und zu beachten. Zuerst die globalen Variablen, dann die statischen Variablen und dann die lokalen Variablen, wie sie im Code erscheinen.

Gerade dieses Beispiel verstößt gegen die Empfehlung der Dokumentation, Variablen nicht mit Funktionen zu initialisieren. Es war für die Entwickler einfacher, eine solche Warnung zu schreiben, als zu erklären, wo sie es können und wo nicht.

Entfernen Sie statische Elemente aus Ihrem Beispiel und Sie erhalten das gewünschte Ergebnis.

 
Alexey Viktorov:

Aber muss die Variable "a" in Ihrem Beispiel global initialisiert werden?

Wenn es sich um eine Konstante handelt (und im globalen Bereich werden Konstanten meistens deklariert, wenn der Code intelligent ist), dann gibt es keine andere Wahl.

Im Skript gibt es keine andere Option, und im EA können Sie eine Variable global deklarieren und sie in OnInit() initialisieren

Es genügt, die Initialisierungssequenz zuverstehen und zu beachten. Zuerst die globalen Variablen, dann die statischen Variablen und dann die lokalen Variablen, wie sie im Code erscheinen.

Gerade dieses Beispiel verstößt gegen die Empfehlung der Dokumentation, Variablen nicht mit Funktionen zu initialisieren. Es war für die Entwickler einfacher, eine solche Warnung zu schreiben, als zu erklären, wo sie es können und wo nicht.

Entfernen Sie statische Elemente aus Ihrem Beispiel und Sie erhalten das gewünschte Ergebnis.

Zu allem, was gelb ist, habe ich eine Frage: WARUM? Ich habe bereits eine Lösung für das Problem gefunden.
 
Die Datei auf der vorherigen Seite wurde aktualisiert. Ein kleiner Fehler wurde korrigiert.
 
Alexey Navoykov:

Wenn es sich um eine Konstante handelt (und globale Sichtbarkeit deklariert meist Konstanten, wenn der Code intelligent ist), gibt es keine andere Wahl.

Zu allem, was gelb ist, habe ich eine Frage: WARUM? Ich habe bereits eine Lösung für das Problem gefunden.

Sie haben einen Weg gefunden, sie zu schaffen.

 
Alexey Navoykov:

Ja, das ist richtig, in regulären Klassen wird sie sofort initialisiert. In Vorlagenklassen ist dies jedoch nicht der Fall:

Sie versuchen, ein statisches Feldeiner Klasse in der Initialisierungsphase zu verwenden, bevor mindestens eine Instanz dieser Klasse erstellt wurde. Meiner Meinung nach ist das eine Perversion... So funktioniert es normalerweise:

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);
};
Der Grundsatz der Kapselung legt im Allgemeinen nahe, dass solche Felder nicht öffentlich, sondern verborgen sein sollten.