Espace de noms

Un namespace (espace de noms) est une zone spécialement déclarée, dans laquelle différents identifiants sont définis : variables, fonctions, classes, etc. Il est défini grâce au mot clé namespace:

namespace nom_de_l'_espace { 
  // liste de définitions de fonctions, classes et variables
}

L'application de "namespace" permet de diviser l'espace de noms global en sous-espaces. Tous les identifiants dans l'espace de noms sont disponibles les uns pour les autres sans spécification. L'opérateur :: (opération de résolution de contexte) est utilisé pour accéder aux membres de l'espace de noms de l'extérieur.

namespace ProjectData
{
class DataManager
  {
public:
   void              LoadData() {}
  };
void Func(DataManagermanager) {}
}
//+------------------------------------------------------------------+
//| Fonction de lancement du programme                               |
//+------------------------------------------------------------------+
void OnStart()
  {
//--- utilisation du namespace ProjectData
   ProjectData::DataManager mgr;
   mgr.LoadData();
   ProjectData::Func(mgr);
  }

Les espaces de noms sont utilisés pour organiser un code sous forme de groupes logiques et pour éviter les conflits de noms qui peuvent se produire lorsque plusieurs bibliothèques sont utilisées dans un programme. Dans de tels cas, chaque bibliothèque peut être déclarée dans son espace de noms pour accéder explicitement aux fonctions et classes nécessaires de chaque bibliothèque.

Un espace de noms peut être déclaré en plusieurs blocs dans un ou plusieurs fichiers. Le compilateur combine toutes les parties ensemble pendant un prétraitement et l'espace de noms résultant contient tous les membres déclarés dans toutes les parties. Supposons que nous ayons une classe A implémentée dans le fichier include Sample.mqh :

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

Nous voulons utiliser cette classe dans notre projet, mais nous avons déjà une classe A. Pour pouvoir utiliser les deux classes et éviter les conflits d'identifiants, enveloppez simplement le fichier inclus dans un espace de noms :

//--- déclaration de la première classe A
class A
  {
public:
                     A() {Print(__FUNCTION__);}
  };
//--- enveloppe la classe A du fichier Sample.mqh dans l'espace de noms Library pour éviter un conflit
namespace Library
{
#include "Sample.mqh"
}
//--- ajout d'une autre classe à l'espace de noms Library
namespace Library
{
class B
  {
public:
                     B() {Print(__FUNCTION__);}
  };
}
//+------------------------------------------------------------------+
//| Fonction de lancement du programme                               |
//+------------------------------------------------------------------+
void OnStart()
  {
//--- utilise la classe A de l'espace de noms global
   A a1;
//--- utilise les classes A et B de l'espace de noms Library
   Library::A a2;
   Library::B b;
  }
//+------------------------------------------------------------------+
 
/*
Résultats :
   A::A
   Library::A::A
   Library::B::B
*/

Les namespaces peuvent être imbriqués. Un espace de noms imbriqué a un accès illimité aux membres de son espace parent, mais les membres de l'espace parent n'ont pas un accès illimité à l'espace de noms imbriqué.

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

 

Espace de noms global

Si l'identifiant n'est pas explicitement déclaré dans l'espace de noms, il est considéré comme faisant partie implicitement de l'espace de noms global. Pour définir explicitement l'identifiant global, utilisez l'opérateur de résolution de portée sans nom. Cela vous permettra de distinguer cet identifiant de tout autre élément portant le même nom situé dans un espace de noms différent. Par exemple, lors de l'import d'une fonction :

#import "lib.dll"
int Func();
#import
//+------------------------------------------------------------------+
//|  Une fonction                                                    |
//+------------------------------------------------------------------+
int Func()
  {
   return(0);
  }
//+------------------------------------------------------------------+
//| Fonction de lancement du programme                               |
//+------------------------------------------------------------------+
void OnStart()
  {
//+--- appelle la fonction importée
   Print(lib::Func());
//+--- appelle notre fonction
   Print(::Func());
  }

Dans ce cas, toutes les fonctions importées de la fonction DLL ont été incluses dans l'espace de noms du même nom. Cela a permis au compilateur de déterminer clairement la fonction à appeler.

Voir aussi

Variables Globales, Variables Locales, Portée de Visibilité et Cycle de Vie des Variables, Création et Suppression des Objets