OOP, modelli e macro in mql5, sottigliezze e usi - pagina 2

 
Ilya Malev:

Ho avuto molte situazioni di dichiarazione di campi statici in classi che sono inizializzate globalmente (prima di OnInit), finché si ri-dichiara il campo statico subito dopo la descrizione della classe, e prima di dichiarare la variabile globale della sua istanza, non c'è mai stato alcun problema con l'inizializzazione del campo statico (perché in questo caso è considerato globale e inizializzato prima dell'istanza della classe come ho capito). Quindi, basta rifiutare di dichiarare variabili statiche all'interno di metodi e funzioni e non c'è alcun problema.

Sì, è vero, viene inizializzato subito nelle classi regolari. Ma non è inizializzato nei template:

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:

Non potete rifiutarvi completamente di dichiarare variabili statiche all'interno di metodi e funzioni, ma almeno non inizializzate altre variabili statiche con quei metodi o funzioni che contengono variabili statiche.

In questo esempio, all'inizio la variabile statica int b sarà inizializzata, ma la variabile statica int f all'interno della funzione int a(int n) non sarà ancora inizializzata e come risultato otterremo dei gibberish.

A proposito, sì, è un altro bug. Cioè, oltre all'inizializzazione separata delle variabili statiche/globali, il codice inizializza le variabili statiche stesse in un ordine sbagliato. Quindi dici "non inizializzare altre variabili statiche con quei metodi o funzioni che contengono variabili statiche" - come suggerisci effettivamente di osservare questo? Ogni funzione è indipendente ed esiste da sola. Ha la sua implementazione, che è soggetta a cambiamenti. Supponiamo che prima non aveva una variabile statica, e poi hai deciso di aggiungerla, il che significa che qualcosa potrebbe andare storto da qualche parte, perché è stato progettato per non avere una variabile statica nella funzione. E come farai a controllare tutto questo?

 
Non capisco questo tipo di decisione di rinunciare a questo o a quello. Perché rinunciare? Per quale motivo? Quando si può risolvere il problema e non negarsi nulla. Beh, ognuno ha la sua scelta...
 
Alexey Navoykov:

A proposito, sì, questo è un altro bug, cioè oltre all'inizializzazione separata di statici/globali rimisurati, inizializza le variabili statiche stesse nell'ordine sbagliato. Quindi dici "non inizializzare altre variabili statiche con quei metodi o funzioni che contengono variabili statiche" - come suggerisci effettivamente di osservare questo? Ogni funzione è indipendente ed esiste da sola. Ha la sua implementazione, che è soggetta a cambiamenti. Supponiamo che prima non aveva una variabile statica, e poi hai deciso di aggiungerla, il che significa che qualcosa potrebbe andare storto da qualche parte, perché è stato progettato per non avere una variabile statica nella funzione. E come farai a controllare tutto questo?

Non è affatto un problema. Basta rifiutare l'inizializzazione delle variabili da parte delle funzioni e tutto andrà a posto.

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

void OnTick()
{
 static int b;
 b=a(9);
}
Funzionerà bene. Qual è il problema? Una linea?
 
Alexey Viktorov:

Funzionerà per uno spasso e un urlo. Qual è il problema? Una linea?

Quindi capisci che la logica è diversa qui? Perché dichiarare b come statico se gli assegni un valore ad ogni chiamata?
 
Alexey Navoykov:
Quindi capisci che la logica è diversa qui? Perché dichiarare b come statico se gli assegni un valore ad ogni chiamata?

Sono d'accordo. Ho fatto un po' di confusione nella fretta. Ma alla variabile 'b' può essere assegnato un valore sotto qualche condizione e invece di 9 valori può essere passata nella funzione a seconda della condizione.


Ma nel tuo esempio, la variabile 'a' deve essere inizializzata 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
};

Non ci sono altre opzioni nello script, e nell'Expert Advisor potete dichiarare la variabile a livello globale e inizializzarla in OnInit()

È sufficiente capire e osservare la sequenza di inizializzazione. Prima le variabili globali, poi le variabili statiche e poi le variabili locali come appaiono nel codice.

Questo stesso esempio viola la raccomandazione della documentazione di non inizializzare le variabili con le funzioni. È stato più facile per gli sviluppatori scrivere un tale avvertimento che spiegare dove possono e non possono.

Rimuovi la statica dal tuo esempio e ottieni il risultato desiderato.

 
Alexey Viktorov:

Ma la variabile 'a' nel tuo esempio deve essere inizializzata globalmente?

Non necessariamente, ma è più conveniente per me. Se è una costante (e le costanti globalmente visibili sono dichiarate per lo più, se il codice è intelligente), allora non c'è altra scelta.

Non ci sono altre opzioni nello script, e nell'EA si può dichiarare una variabile globalmente e inizializzarla in OnInit()

È sufficiente capire e osservare la sequenza di inizializzazione. Prima le variabili globali, poi le variabili statiche e poi le variabili locali come appaiono nel codice.

Questo stesso esempio viola la raccomandazione della documentazione di non inizializzare le variabili con le funzioni. È stato più facile per gli sviluppatori scrivere un tale avvertimento che spiegare dove possono e non possono.

Rimuovi la statica dal tuo esempio e ottieni il risultato desiderato.

Riguardo a tutto ciò che è in giallo, ho una domanda: PERCHE'? Ho già trovato come risolvere il problema.
 
Aggiornato il file nella pagina precedente. Corretto un piccolo difetto.
 
Alexey Navoykov:

Non necessariamente, ma è più conveniente per me. Se è una costante (e la visibilità globale dichiara per lo più costanti, se il codice è competente), non c'è altra scelta qui.

Riguardo a tutto ciò che è in giallo, ho una domanda: PERCHE'? Ho già trovato come risolvere il problema.

Avete trovato un modo per crearlo.

 
Alexey Navoykov:

Sì, è vero, nelle classi regolari viene inizializzato immediatamente. Ma nelle classi template non lo è:

State cercando di usare un campo staticodi una classe in fase di inizializzazione prima che sia stata creata almeno 1 istanza di quella classe. Secondo me, questa è una perversione... Questo è il modo in cui funziona 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);
};
Il principio dell'incapsulamento in generale suggerisce che tali campi dovrebbero essere nascosti piuttosto che pubblici.
Motivazione: