GeeksforGeeks
On janvier 16, 2022 by adminL’énoncé using namespace std est généralement considéré comme une mauvaise pratique. L’alternative à cette déclaration est de spécifier l’espace de noms auquel l’identifiant appartient en utilisant l’opérateur scope(: 🙂 chaque fois que nous déclarons un type.
Bien que l’instruction nous évite de taper std: : chaque fois que nous souhaitons accéder à une classe ou un type défini dans l’espace de noms std, elle importe l’intégralité de l’espace de noms std dans l’espace de noms actuel du programme. Prenons quelques exemples pour comprendre pourquoi cela pourrait ne pas être une si bonne chose
Disons que nous souhaitons utiliser le cout de l’espace de nom std. Nous écrivons donc
Exemple 1 :
#include <iostream>
using
. namespace
std;
cout <<
" Something to Display"
;
Maintenant, à un stade ultérieur de développement, nous souhaitons utiliser une autre version de cout qui est implémentée de manière personnalisée dans une bibliothèque appelée « foo » (par exemple)
.
#include <foo.h>
#include <iostream>
using
namespace
std;
cout <<
" Something to display"
;
Voir comment il y a une ambiguité, vers quelle bibliothèque cout pointe-t-il ? Le compilateur peut le détecter et ne pas compiler le programme. Dans le pire des cas, le programme peut tout de même compiler mais appeler la mauvaise fonction, puisque nous n’avons jamais précisé à quel espace de noms appartenait l’identifiant.
Les espaces de noms ont été introduits dans le C++ pour résoudre les conflits de noms d’identifiants. Cela garantissait que deux objets puissent avoir le même nom et pourtant être traités différemment s’ils appartenaient à des espaces de noms différents. Remarquez que c’est exactement le contraire qui s’est produit dans cet exemple. Au lieu de résoudre un conflit de noms, nous créons en fait un conflit de noms.
Lorsque nous importons un espace de noms, nous attirons essentiellement toutes les définitions de types dans la portée actuelle. L’espace de noms std est énorme. Il possède des centaines d’identifiants prédéfinis, il est donc possible qu’un développeur néglige le fait qu’il existe une autre définition de son objet prévu dans la bibliothèque std. Sans en être conscient, il peut spécifier sa propre implémentation et s’attendre à ce qu’elle soit utilisée dans les parties ultérieures du programme. Ainsi, il existerait deux définitions pour le même type dans l’espace de noms actuel. Ceci n’est pas autorisé en C++, et même si le programme se compile, il n’y a aucun moyen de savoir quelle définition est utilisée à quel endroit.
La solution à ce problème est de spécifier explicitement à quel espace de noms notre identifiant appartient en utilisant l’opérateur scope (: :). Ainsi, une solution possible à l’exemple ci-dessus peut être
.
.
#include <foo>
#include <iostream>
std::cout <<
"Something to display"
;
foo::cout <
"Something to display"
;
Mais devoir taper std :: chaque fois que nous définissons un type est fastidieux. Cela rend également notre code plus chevelu avec beaucoup de définitions de types et rend difficile la lecture du code. Considérons par exemple le code pour obtenir l’heure actuelle dans le programme
Exemple 2 :
#include <chrono>
#include <iostream>
auto
start = std::chrono::high_performance_clock::now()
auto
stop
= std::chrono::high_peformance_clock::now();
auto
duration
= std::duration_cast<std::chrono::milliseconds>(stop - start);
Le code source qui est jonché de définitions de types compliquées et longues n’est pas très facile à lire. C’est quelque chose que les développeurs cherchent à éviter puisque la maintenabilité du code est principalement importante pour eux.
Il y a quelques façons de résoudre ce dilemme c’est-à-dire spécifier l’espace de noms exact sans joncher le code de mots-clés std.
Envisager d’utiliser des typedefs
les typedefs nous évitent d’écrire de longues définitions de types. Dans notre exemple 1, nous pourrions résoudre le problème en utilisant deux typedefs, un pour la bibliothèque std et un autre pour foo
#include <foo>
#include <iostream>
typedef
std::cout cout_std;
typedef
foo::cout cout_foo;
cout_std <<
"Something to write"
;
cout_foo <<
"Something to write"
;
Au lieu d’importer des espaces de noms entiers, importez un espace de noms tronqué
Dans l’exemple 2, nous aurions pu importer uniquement l’espace de noms chrono sous std.
#include <chrono>
#include <iostream>
using
std::chrono;
auto
start = high_performance_clock::now();
auto
stop = high_performance_clock::now();
auto
duration duration_cast<milliseconds>(stop - start);
On peut aussi utiliser l’instruction pour importer un seul identifiant. Pour importer seulement std::cout, nous pourrions utiliser
using std::cout;
Si vous importez toujours des espaces de noms entiers, essayez de le faire à l’intérieur de fonctions ou de portée limitée et non dans la portée globale.
Utilisez l’instruction « using namespace std » à l’intérieur des définitions de fonctions ou de classes, de structures. Ce faisant, les définitions de l’espace de nom sont importées dans une portée locale, et nous savons au moins d’où peuvent provenir les erreurs éventuelles si elles se produisent.
#include <isotream>
using
namespace
std;
void
foo()
{
using
namespace
std;
}
Conclusion.
Nous avons discuté des méthodes alternatives pour accéder à un identifiant depuis un espace de noms. Dans tous les cas, évitez d’importer des espaces de noms entiers dans le code source.
Bien que les bonnes pratiques de codage puissent prendre un certain temps à apprendre et à développer, elles sont généralement payantes à long terme. Écrire un code propre, sans ambiguïté et robuste sans erreur devrait être l’intention de tout développeur de programmation.
Laisser un commentaire