Maîtriser les espaces de noms en C++ : Éviter les conflits de fonctions
Considérez une situation où nous avons deux personnes avec le même nom, Zara, dans la même classe. Chaque fois que nous devons les différencier, nous devrions certainement utiliser des informations supplémentaires avec leur nom, comme la zone où ils habitent s'ils habitent dans des zones différentes ou le nom de leur mère ou père, etc.
La même situation peut survenir dans vos applications C++. Par exemple, vous pourriez écrire du code qui a une fonction appelée xyz() et il y a une autre bibliothèque disponible qui a aussi la même fonction xyz(). Maintenant, le compilateur n'a aucun moyen de savoir quelle version de la fonction xyz() vous référencez dans votre code.
Un espace de noms (namespace) est conçu pour surmonter cette difficulté et est utilisé comme information additionnelle pour différencier des fonctions, classes, variables, etc. similaires avec le même nom disponibles dans différentes bibliothèques. En utilisant un espace de noms, vous pouvez définir le contexte dans lequel les noms sont définis. En essence, un espace de noms définit une portée.
Définition d'un espace de noms
Une définition d'espace de noms commence avec le mot-clé namespace suivi du nom de l'espace de noms comme suit :
namespace nom_espace_noms {
// déclarations de code
}
Pour appeler la version activée par l'espace de noms d'une fonction ou variable, préfixez (::) le nom de l'espace de noms comme suit :
nom::code; // code pourrait être variable ou fonction.
Voyons comment l'espace de noms délimite les entités incluant variables et fonctions :
#include <iostream>
using namespace std;
// premier espace de noms
namespace first_space {
void func() {
cout << "À l'intérieur de first_space" << endl;
}
}
// second espace de noms
namespace second_space {
void func() {
cout << "À l'intérieur de second_space" << endl;
}
}
int main() {
// Appelle la fonction du premier espace de noms.
first_space::func();
// Appelle la fonction du second espace de noms.
second_space::func();
return 0;
}
Si nous compilons et exécutons le code ci-dessus, cela produirait le résultat suivant :
À l'intérieur de first_space À l'intérieur de second_space
La directive using
Vous pouvez aussi éviter le préfixage des espaces de noms avec la directive using namespace. Cette directive dit au compilateur que le code subséquent utilise les noms dans l'espace de noms spécifié. L'espace de noms est ainsi implicite pour le code suivant :
#include <iostream>
using namespace std;
// premier espace de noms
namespace first_space {
void func() {
cout << "À l'intérieur de first_space" << endl;
}
}
// second espace de noms
namespace second_space {
void func() {
cout << "À l'intérieur de second_space" << endl;
}
}
using namespace first_space;
int main() {
// Ceci appelle la fonction du premier espace de noms.
func();
return 0;
}
Si nous compilons et exécutons le code ci-dessus, cela produirait le résultat suivant :
À l'intérieur de first_space
La directive 'using' peut aussi être utilisée pour référencer un élément particulier dans un espace de noms. Par exemple, si la seule partie de l'espace de noms std que vous avez l'intention d'utiliser est cout, vous pouvez vous y référer comme suit :
using std::cout;
Le code subséquent peut se référer à cout sans préfixer l'espace de noms, mais les autres éléments dans l'espace de noms std devront encore être explicites comme suit :
#include <iostream>
using std::cout;
int main() {
cout << "std::endl est utilisé avec std !" << std::endl;
return 0;
}
Si nous compilons et exécutons le code ci-dessus, cela produirait le résultat suivant :
std::endl est utilisé avec std !
Les noms introduits dans une directive using obéissent aux règles de portée normales. Le nom est visible depuis le point de la directive using jusqu'à la fin de la portée dans laquelle la directive est trouvée. Les entités avec le même nom définies dans une portée externe sont masquées.
Espaces de noms discontinus
Un espace de noms peut être défini en plusieurs parties et donc un espace de noms est constitué de la somme de ses parties définies séparément. Les parties séparées d'un espace de noms peuvent être réparties sur plusieurs fichiers.
Donc, si une partie de l'espace de noms requiert un nom défini dans un autre fichier, ce nom doit encore être déclaré. Écrire une définition d'espace de noms suivante définit soit un nouvel espace de noms, soit ajoute de nouveaux éléments à un existant :
namespace nom_espace_noms {
// déclarations de code
}
Espaces de noms imbriqués
Les espaces de noms peuvent être imbriqués où vous pouvez définir un espace de noms à l'intérieur d'un autre espace de noms comme suit :
namespace nom_espace_noms1 {
// déclarations de code
namespace nom_espace_noms2 {
// déclarations de code
}
}
Vous pouvez accéder aux membres d'un espace de noms imbriqué en utilisant les opérateurs de résolution comme suit :
// pour accéder aux membres de nom_espace_noms2 using namespace nom_espace_noms1::nom_espace_noms2; // pour accéder aux membres de nom_espace_noms1 using namespace nom_espace_noms1;
Dans les instructions ci-dessus, si vous utilisez nom_espace_noms1, alors cela rendra les éléments de nom_espace_noms2 disponibles dans la portée comme suit :
#include <iostream>
using namespace std;
// premier espace de noms
namespace first_space {
void func() {
cout << "À l'intérieur de first_space" << endl;
}
// second espace de noms
namespace second_space {
void func() {
cout << "À l'intérieur de second_space" << endl;
}
}
}
using namespace first_space::second_space;
int main() {
// Ceci appelle la fonction du second espace de noms.
func();
return 0;
}
Si nous compilons et exécutons le code ci-dessus, cela produirait le résultat suivant :
À l'intérieur de second_space
Langue C
- Maîtriser les opérateurs C++ : Guide complet avec exemples pratiques
- Commentaires C++ : Bonnes pratiques pour un code lisible et maintenable
- Maîtriser les templates de classe en C++ : Guide pratique
- Langage C++ : Vue d'ensemble et caractéristiques clés
- Constantes et littéraux en C++ : Types, syntaxe et bonnes pratiques
- Guide complet des opérateurs C++ : Types, utilisation et bonnes pratiques
- Maîtriser les types numériques en C++ : Guide pratique
- Comprendre les références en C++ : Concepts clés et différences avec les pointeurs
- Maîtriser les espaces de noms en C++ : Éviter les conflits de fonctions