1. Chapitre XII
Namespaces
• Un namespace (espace de nommage ou espace de noms) est une zone qui permet de
délimiter la recherche des noms des identificateurs par le compilateur. Il sert
essentiellement à regrouper les identificateurs pour éviter les conflits de noms entre
plusieurs parties d'un projet
• C++ offre un seul namespace de portée globale, dans le quel il ne doit avoir aucun
conflit de nom. Avec les namespaces non globaux, on peut définir des objets globaux,
sans qu'ils aient une portée globale
Définition
• On définit un espace de noms avec le mot clé namespace comme suit :
namespace nom
{
// Déclarations et définitions
}
Où nom est le nom de l'espace de noms
2. Namespaces 116
• La définition d'un namespace peut être découpée en plusieurs parties, comme par
exemple:
namespace A
{
int n;
}
namespace B
{
int n;
float a;
}
namespace A
{
float b;
}
• Un namespace peut contenir d'autres namespaces. D'autre part, on peut définir un
namespace sans nom, les espaces de noms qui n'ont pas de noms sont dits anonymes.
L'espace de nom de portée globale définit dans C++ est un espace de nom anonyme.
• Il est possible de donner un autre nom (alias) à un espace de noms, pour ce, on utilise
la syntaxe suivante :
namespace nom_alias = nom;
Accès et définition des membres d'un namespace
• Pour accéder à un objet ou une fonction définie dans un namespce à l'extérieur de
celui-ci, on utilise l'opérateur de résolution de portée :
int n; // globale
namespace A
{
int n;
void f1();
int f2() {… …}
}
void A::f1() { … …}
… …
void main()
{
A::n = 0; // n définit dans A
n = 1; // n globale
}
• Si, dans un espace de noms, un identificateur est déclaré avec le même nom qu’un
autre identificateur déclaré dans un espace de noms plus global, l’identificateur global
est masqué.
• Pour accéder à un identificateur en dehors de son espace de noms, il faut utiliser un
nom complètement qualifié à l’aide de l’opérateur de résolution de portée. Toutefois,
si l’espace de noms dans lequel il est défini est un espace de noms anonyme, cet
identificateur ne pourra pas être référencé, puisqu’on ne peut pas préciser le nom des
espaces de noms anonymes.
3. Namespaces 117
Déclaration using
• La déclaration using permet d’utiliser un identificateur d’un espace de noms de
manière simplifiée, sans avoir à spécifier son nom complet :
using identificateur;
Ainsi, on a par exemple :
namespace A
{
int n;
}
… …
void main()
{
using A::n;
n = 1; // fait référence à A::n;
}
• Une déclaration using peut être utilisée dans la définition d’une classe. Dans ce cas,
elle doit se rapporter à une classe de base de la classe dans laquelle elle est utilisée. De
plus, l’identificateur donné à la déclaration using doit être accessible dans la classe de
base.
namespace A
{
float f;
}
class B
{
int i;
public:
int j;
};
class T : public B
{
using A::f; // Illégal : f n’est pas dans une classe de base.
using B::i; // Interdit : B::i est inaccessible
public:
using B::j; // Légal.
};
• La déclaration using sert au fait à rétablir certains droits d'accès, modifiés par un
héritage : Pour cela on doit déclarer le membre avec using dans une zone de
déclaration de même type.
class B
{
public:
int i;
int j;
};
class T : private B
{
public:
using B::i; // Rétablit l’accessibilité sur B::i.
protected:
using B::j; // Interdit : zone de déclaration différente
};
4. Namespaces 118
Directive using
La directive using permet d’utiliser tous les identificateurs d'un espace de noms, sans
spécification de cet espace de nom
using namespace nom;
où nom est le nom de l’espace de noms dont les identificateurs seront utilisés sans
qualification complète.
namespace A
{
int n;
void f1();
}
… …
void fct()
{
using namespace A;
n = 0; // reference à A::n
f1(); // appel de A::f1()
}