« Programmation C++/Les espaces de noms » : différence entre les versions

Un livre de Wikilivres.
Contenu supprimé Contenu ajouté
Gzen92 (discussion | contributions)
typo
DannyS712 (discussion | contributions)
m <source> -> <syntaxhighlight> (phab:T237267)
Ligne 15 : Ligne 15 :


Pour simplifier le code, et les désigner sans spécifier l'espace de noms, il faut utiliser l'instruction suivante :
Pour simplifier le code, et les désigner sans spécifier l'espace de noms, il faut utiliser l'instruction suivante :
<source lang="cpp">
<syntaxhighlight lang="cpp">
using namespace std;
using namespace std;
</syntaxhighlight>
</source>


Utiliser différents espaces de noms permet, lors d'un projet en équipe ou de l'utilisation de bibliothèque externes, de créer plusieurs entités portant le même nom.
Utiliser différents espaces de noms permet, lors d'un projet en équipe ou de l'utilisation de bibliothèque externes, de créer plusieurs entités portant le même nom.
Ligne 24 : Ligne 24 :


Pour déclarer vos fonctions, variables et classes dans votre espace de noms, placez-les dans un bloc de ce type :
Pour déclarer vos fonctions, variables et classes dans votre espace de noms, placez-les dans un bloc de ce type :
<source lang="cpp">
<syntaxhighlight lang="cpp">
namespace identifiant
namespace identifiant
{
{
// Déclarations ici ...
// Déclarations ici ...
}
}
</syntaxhighlight>
</source>


Exemple :
Exemple :
<source lang="cpp">
<syntaxhighlight lang="cpp">
namespace exemple
namespace exemple
{
{
Ligne 39 : Ligne 39 :
}
}
}
}
</syntaxhighlight>
</source>


== Utiliser un espace de noms ==
== Utiliser un espace de noms ==
Pour utiliser les entités d'un espace de noms en dehors de celui-ci (voire dans un autre espace de noms), vous pouvez utiliser le nom précédé de l'espace de nom :
Pour utiliser les entités d'un espace de noms en dehors de celui-ci (voire dans un autre espace de noms), vous pouvez utiliser le nom précédé de l'espace de nom :
<source lang="cpp">
<syntaxhighlight lang="cpp">
int a = exemple::suivant(5);
int a = exemple::suivant(5);
</syntaxhighlight>
</source>


ou utiliser la déclaration <code>using</code> :
ou utiliser la déclaration <code>using</code> :
<source lang="cpp">
<syntaxhighlight lang="cpp">
using exemple::suivant;
using exemple::suivant;
...
...
int a = suivant(5);
int a = suivant(5);
</syntaxhighlight>
</source>


ou encore utiliser la directive <code>using</code>
ou encore utiliser la directive <code>using</code>


<source lang="cpp">
<syntaxhighlight lang="cpp">
using namespace exemple;
using namespace exemple;
...
...
int a = suivant(5);
int a = suivant(5);
</syntaxhighlight>
</source>


'''Recommandation''': Il est préférable de ne pas utiliser les directives <code>using</code> dans un fichier entête, excepté dans les fonctions ''inline''. En effet, la directive ayant pour effet d'ouvrir l'espace de noms à l'espace global, toute unité qui inclurait ce fichier entête se verrait automatiquement ouvrir l'espace en question pouvant provoquer rapidement des collisions si cette même unité incluait d'autres fichiers entêtes utilisant aussi la directive <code>using</code> sur d'autres espaces de noms.
'''Recommandation''': Il est préférable de ne pas utiliser les directives <code>using</code> dans un fichier entête, excepté dans les fonctions ''inline''. En effet, la directive ayant pour effet d'ouvrir l'espace de noms à l'espace global, toute unité qui inclurait ce fichier entête se verrait automatiquement ouvrir l'espace en question pouvant provoquer rapidement des collisions si cette même unité incluait d'autres fichiers entêtes utilisant aussi la directive <code>using</code> sur d'autres espaces de noms.
Ligne 68 : Ligne 68 :


Exemple:
Exemple:
<source lang="cpp">
<syntaxhighlight lang="cpp">
namespace global {
namespace global {
namespace exemple {
namespace exemple {
Ligne 77 : Ligne 77 :
namespace ge = global::exemple; // alias
namespace ge = global::exemple; // alias
int a = ge::suivant(5);
int a = ge::suivant(5);
</syntaxhighlight>
</source>


== En plusieurs fois ==
== En plusieurs fois ==
Ligne 85 : Ligne 85 :
*Fichier '''exemple.h'''
*Fichier '''exemple.h'''


<source lang="cpp">
<syntaxhighlight lang="cpp">
namespace exemple
namespace exemple
{
{
int suivant(int n);
int suivant(int n);
}
}
</syntaxhighlight>
</source>


*Fichier '''exemple.cpp'''
*Fichier '''exemple.cpp'''


<source lang="cpp">
<syntaxhighlight lang="cpp">
#include "exemple.h"
#include "exemple.h"


Ligne 103 : Ligne 103 :
}
}
}
}
</syntaxhighlight>
</source>

Version du 16 avril 2020 à 09:32

Introduction

Les espaces de nom ont été introduits pour permettre de faire des regroupements logiques et résoudre les collisions de noms. Un espace de nom permet de regrouper plusieurs déclarations de variables, fonctions et classes dans un groupe nommé. Une pratique courante du langage C consistant à concaténer des noms entre eux afin de minimiser la probabilité de collisions avec des noms d'autres bibliothèques n'a plus raison d'être en C++. En effet, un même nom pourra être déclaré dans des espaces de noms différents évitant ainsi la collision lorsqu'ils sont inclus en même temps dans une unité.

La déclaration d'un espace de noms se fait à l'aide du mot clé namespace.

Tout comme l'accès à un membre d'une classe, l'opérateur de portée :: permet l'accès à l'ensemble des noms importés d'un espace de noms.

Avant l'introduction des espaces de noms, une pratique du C++ consistait à utiliser des classes pour faire des espaces de noms. Le problème est qu'une classe est instanciable et que sa portée est fermée. A contrario, la portée d'un espace de noms est ouvert, c'est-à-dire qu'il est possible de répartir un espace de noms sur plusieurs unités. Un espace de noms est donc extensible.

Enfin, il est possible d'imbriquer un espace de noms dans un autre espace de noms.

Un exemple d'espace de nom est std, défini par la bibliothèque standard, regroupant en autre les flux standards cin, cout et cerr. Ainsi lorsque <iostream> est inclus dans une source, il sera possible de les accéder en les dénommant par leurs noms complets std::cin, std::cout et std::cerr.

Pour simplifier le code, et les désigner sans spécifier l'espace de noms, il faut utiliser l'instruction suivante :

using namespace std;

Utiliser différents espaces de noms permet, lors d'un projet en équipe ou de l'utilisation de bibliothèque externes, de créer plusieurs entités portant le même nom.

Créer un espace de noms

Pour déclarer vos fonctions, variables et classes dans votre espace de noms, placez-les dans un bloc de ce type :

namespace identifiant
{
    // Déclarations ici ...
}

Exemple :

namespace exemple
{
    int suivant(int n) {
        return n+1;
    }
}

Utiliser un espace de noms

Pour utiliser les entités d'un espace de noms en dehors de celui-ci (voire dans un autre espace de noms), vous pouvez utiliser le nom précédé de l'espace de nom :

int a = exemple::suivant(5);

ou utiliser la déclaration using :

using exemple::suivant;
...
int a = suivant(5);

ou encore utiliser la directive using

using namespace exemple;
...
int a = suivant(5);

Recommandation: Il est préférable de ne pas utiliser les directives using dans un fichier entête, excepté dans les fonctions inline. En effet, la directive ayant pour effet d'ouvrir l'espace de noms à l'espace global, toute unité qui inclurait ce fichier entête se verrait automatiquement ouvrir l'espace en question pouvant provoquer rapidement des collisions si cette même unité incluait d'autres fichiers entêtes utilisant aussi la directive using sur d'autres espaces de noms.

Alias d'espace de noms

Une autre manière très pratique d'utiliser un espace de noms surtout lorsque celui-ci est imbriqué dans d'autres espaces de noms sur plusieurs niveaux est l'emploi d'alias. Un alias permet de ramener une portée à un seul nom.

Exemple:

namespace global {
namespace exemple { 
   int suivant(int n);
} // namespace exemple
} // namespace global
...
namespace ge = global::exemple;  // alias
int a = ge::suivant(5);

En plusieurs fois

Vous pouvez ajouter des déclarations à un espace de noms existant, par exemple lorsque vous utilisez un fichier d'en-tête et un fichier d'implémentation :

  • Fichier exemple.h
namespace exemple
{
    int suivant(int n);
}
  • Fichier exemple.cpp
#include "exemple.h"

namespace exemple
{
    int suivant(int n) {
        return n+1;
    }
}