Namespaces

Un namespace è un'area dichiarata appositamente, all'interno della quale sono definiti vari ID: variabili, funzioni, classi, ecc. Si imposta usando la parola chiave namespace parola chiave:

namespace nome dello_spazio { 
// elenco di definizioni di funzioni, classi e variabili
}

L'applicazione del 'namespace' consente di suddividere il namespace globale in subspaces(sottospazi). Tutti gli ID all'interno del namespace sono disponibili gli uni agli altri senza una specifica. L' operatore :: (operazione di risoluzione del contesto) viene utilizzato per accedere ai membri del namespace dall'esterno.

namespace ProjectData
{
class DataManager
  {
public:
   void              LoadData() {}
  };
void Func(DataManagermanager) {}
}
//+------------------------------------------------------------------+
//| Funzione di avvio del programma di script |
//+------------------------------------------------------------------+
void OnStart()
  {
//--- lavorare con il namespace ProjectData
ProjectData::DataManagermgr;
   mgr.LoadData();
   ProjectData::Func(mgr);
  }

I namespaces vengono utilizzati per disporre un codice sotto forma di gruppi logici ed evitare conflitti di nomi che possono verificarsi quando si utilizzano più librerie in un programma. In tali casi, ciascuna libreria può essere dichiarata nel suo namespace per accedere esplicitamente alle funzioni ed alle classi necessarie di ciascuna libreria.

Un namespace può essere dichiarato in più blocchi in uno o più file. Il compilatore combina tutte le parti insieme durante il preprocessing(preelaborazione) ed il namespace risultante contiene tutti i membri dichiarati in tutte le parti. Supponiamo di avere una classe implementata nel file include Sample.mqh:

//+------------------------------------------------------------------+
//|                                                       Sample.mqh |
//+------------------------------------------------------------------+
class A
  {
public:
                     A() {Print(__FUNCTION__);}
  };

Vogliamo usare questa classe nel nostro progetto, ma abbiamo già una classe A. Per poter utilizzare entrambe le classi ed evitare conflitti di ID, è sufficiente avvolgere il file incluso in un namespace:

//--- dichiara la prima classe A.
class A
  {
public:
                     A() {Print(__FUNCTION__);}
  };
//--- avvolge la classe A dal file Sample.mqh nel namespace Library per evitare un conflitto
namespace Library
{
#include "Sample.mqh"
}
//--- aggiunge ancora un'altra classe al namespace Library
namespace Library
{
class B
  {
public:
                     B() {Print(__FUNCTION__);}
  };
}
//+------------------------------------------------------------------+
//| Funzione di avvio del programma di script |
//+------------------------------------------------------------------+
void OnStart()
  {
//--- usa la classe A dal namespace globale
   A a1;
//--- usa le classi A e B dal namespace Library 
   Library::A a2;
   Library::B b;
  }
//+------------------------------------------------------------------+
 
/*
Risultato:
   A::A
   Library::A::A
   Library::B::B
*/

I namespaces possono essere nidificati. Uno namespace nidificato ha accesso illimitato ai membri del suo spazio genitore, ma i membri dello spazio genitore non hanno accesso illimitato al namespace nidificato.

namespace General
{
int Func();
 
namespace Details
{
 int Counter;
 int Refresh()  {return Func(); }
}
 
int GetBars()   {return(iBars(Symbol(), Period()));};
int Size(int i) {return Details::Counter;}
}

 

Namespace Globale

Se l'ID non viene dichiarato esplicitamente nel namespace, viene considerato una parte implicita del namespace globale. Per impostare l'ID globale in modo esplicito, utilizzare l'operatore di risoluzione dell'ambito senza un nome. Ciò ti consentirà di distinguere questo ID da qualsiasi altro elemento con lo stesso nome situato in un namespace diverso. Ad esempio, quando si importa una funzione:

#import "lib.dll"
int Func();
#import
//+------------------------------------------------------------------+
//| Alcune funzioni |
//+------------------------------------------------------------------+
int Func()
  {
   return(0);
  }
//+------------------------------------------------------------------+
//| Funzione di avvio del programma di script |
//+------------------------------------------------------------------+
void OnStart()
  {
//+--- chiama la funzione importata
   Print(lib::Func());
//+--- chiama la nostra funzione
   Print(::Func());
  }

In questo caso, tutte le funzioni importate dalla funzione DLL sono state incluse nel namespace con lo stesso nome. Ciò ha permesso al compilatore di determinare chiaramente la funzione da chiamare.

Guarda anche

Variabili globali, Variabili locali, Ambito di Visibilità e Durata delle Variabili, Creazione ed Eliminazione di Oggetti