c++ try Pourquoi l'utilisation de namespace std est-elle considérée comme une mauvaise pratique?




new try catch c++ (24)

D'autres personnes m'ont dit qu'écrire en using namespace std dans le code était une erreur et que je devrais plutôt utiliser std::cout et std::cin directement.

Pourquoi l' using namespace std considérée comme une mauvaise pratique? Est-ce inefficace ou risque-t-il de déclarer des variables ambiguës (variables qui partagent le même nom qu'une fonction dans un espace de noms std )? Cela at-il un impact sur les performances?


Si vous importez les fichiers d'en-tête de droite, vous avez soudainement des noms comme hex , left , plus ou count dans votre étendue globale. Cela peut être surprenant si vous n’êtes pas conscient que std:: contient ces noms. Si vous essayez également d'utiliser ces noms localement, vous risquez de créer une certaine confusion.

Si tout le contenu standard se trouve dans son propre espace de noms, vous n'avez pas à vous soucier des conflits de noms avec votre code ou d'autres bibliothèques.


Cela n'empêche pas les performances de votre logiciel ou de votre projet, l'inclusion de l'espace de nom au début de votre code source n'est pas une mauvaise chose. L'inclusion de l' using namespace stdinstruction varie en fonction de vos besoins et de la manière dont vous développez le logiciel ou le projet.

Le namespace stdcontient les fonctions standard et les variables C ++. Cet espace de noms est utile lorsque vous utilisez souvent les fonctions standard C ++.

Comme mentionné dans cette page :

L'instruction utilisant namespace std est généralement considérée comme une mauvaise pratique. L’alternative à cette instruction est de spécifier l’espace de noms auquel appartient l’identifiant à l’aide de l’opérateur scope (: :) à chaque fois que nous déclarons un type.

Et voir cette opinion :

Il n’ya aucun problème à utiliser "namespace std" dans votre fichier source lorsque vous utilisez abondamment l’espace de nommage et que vous êtes certain que rien ne va se heurter.

Certaines personnes ont dit qu'il est déconseillé d'inclure les using namespace stdfichiers dans vos fichiers source, car vous appelez depuis cet espace de noms toutes les fonctions et variables. Lorsque vous souhaitez définir une nouvelle fonction portant le même nom qu’une autre fonction contenue dans le namespace stdfichier, vous surchargez la fonction, ce qui peut entraîner des problèmes de compilation ou d’exécution. Il ne sera pas compilé ou exécuté comme prévu.

Comme mentionné dans cette page :

Bien que l'instruction nous évite de saisir 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

...

Maintenant, à un stade ultérieur du développement, nous souhaitons utiliser une autre version de cout personnalisée dans une bibliothèque appelée «foo» (par exemple).

...

Notez qu’il ya une ambiguïté, à quelle bibliothèque le cout pointe-t-il? Le compilateur peut détecter cela et ne pas compiler le programme. Dans le pire des cas, le programme peut toujours compiler mais appeler la mauvaise fonction, car nous n'avons jamais spécifié à quel espace de nom appartient l'identificateur.


J'ai récemment eu une plainte concernant Visual Studio 2010 . Il s’est avéré que pratiquement tous les fichiers source avaient ces deux lignes:

using namespace std;
using namespace boost;

De nombreuses fonctionnalités de Boost sont intégrées à la norme C ++ 0x et Visual Studio 2010 comporte de nombreuses fonctionnalités C ++ 0x. Par conséquent, ces programmes ne se sont pas compilés.

Par conséquent, éviter d' using namespace X; est une forme d'avenir, une façon de s'assurer qu'une modification des bibliothèques et / ou des fichiers d'en-tête utilisés ne va pas casser un programme.


Je conviens qu'il ne devrait pas être utilisé globalement, mais ce n'est pas si mal d'utiliser localement, comme dans un namespace . Voici un exemple tiré de "Le langage de programmation C ++" :

namespace My_lib {

    using namespace His_lib; // everything from His_lib
    using namespace Her_lib; // everything from Her_lib

    using His_lib::String; // resolve potential clash in favor of His_lib
    using Her_lib::Vector; // resolve potential clash in favor of Her_lib

}

Dans cet exemple, nous avons résolu les conflits de noms potentiels et les ambiguïtés découlant de leur composition.

Les noms explicitement déclarés ici (y compris les noms déclarés en utilisant des déclarations comme His_lib::String ) ont priorité sur les noms rendus accessibles dans une autre portée par une directive using namespace Her_lib (en using namespace Her_lib ).


Une autre raison est la surprise.

Si je vois cout << blah , au lieu de std::cout << blah

Je pense quel est ce cout ? Est-ce le cout normal? Est-ce quelque chose de spécial?


Ce n'est pas du tout lié à la performance. Mais considérez ceci: vous utilisez deux bibliothèques appelées Foo et Bar:

using namespace foo;
using namespace bar;

Tout fonctionne bien, vous pouvez appeler Blah() de Foo et Quux() de Bar sans problèmes. Mais un jour, vous passez à une nouvelle version de Foo 2.0, qui offre maintenant une fonction appelée Quux() . Vous avez maintenant un conflit: Foo 2.0 et Bar importent Quux() dans votre espace de noms global. Cela demandera un certain effort, en particulier si les paramètres de la fonction correspondent.

Si vous aviez utilisé foo::Blah() et bar::Quux() , alors l'introduction de foo::Quux() aurait été un non-événement.


D'après mes expériences, si vous avez plusieurs bibliothèques qui utilisent say cout, mais vous pouvez utiliser le mauvais dans un but différent cout.

Par exemple, si je saisis, using namespace std;et que je ne fais que using namespace otherlib;simplement cout (plutôt que std::cout(ou 'otherlib::cout'), vous pourriez utiliser le mauvais, et obtenir des erreurs, son utilisation est beaucoup plus efficace et efficiente std::cout.


Je suis d'accord avec les autres - il demande des conflits de noms, des ambiguïtés et le fait est que c'est moins explicite. Bien que je puisse en voir l’utilisation using, ma préférence personnelle est de la limiter. J'examinerais aussi fortement ce que d'autres ont souligné:

Si vous voulez trouver un nom de fonction qui pourrait être un nom assez commun, mais que vous voulez seulement le trouver dans l' stdespace de noms (ou inversement, vous voulez modifier tous les appels qui ne sont PAS dans l'espace de noms std, l'espace de noms X, ...), alors comment proposez-vous cela? Vous pouvez écrire un programme pour le faire, mais ne serait-il pas préférable de passer du temps à travailler sur votre projet lui-même plutôt que d'écrire un programme pour maintenir votre projet?

Personnellement, le std::préfixe ne me dérange pas . J'aime le look plus que ne pas l'avoir. Je ne sais pas si c'est parce que c'est explicite et me dit "ce n'est pas mon code ... j'utilise la bibliothèque standard" ou s'il s'agit d'autre chose, mais je pense que c'est plus joli. Cela peut paraître étrange étant donné que je n’ai commencé que récemment à utiliser le langage C ++ (le C et d’autres langages sont encore utilisés depuis bien plus longtemps et C est mon langage préféré de tous les temps, juste au-dessus de l’assemblage).

Il y a une autre chose, bien qu'elle soit un peu liée à ce qui précède et à ce que d'autres soulignent. Bien que cela puisse être une mauvaise pratique, je réserve parfois std::nameune version de bibliothèque standard et un nom pour une implémentation spécifique à un programme. Oui, en effet, cela pourrait vous mordre et vous mordre fort mais tout se résume à ce que j'ai commencé ce projet à partir de zéro et que je suis le seul programmeur pour cela. Exemple: je surcharge std::stringet l'appelle string. J'ai des ajouts utiles. Je l'ai fait en partie à cause de ma tendance à C et Unix (+ Linux) vers les noms en minuscules.

En plus de cela, vous pouvez avoir des alias d'espace de noms. Voici un exemple de cas où il est utile de ne pas avoir été mentionné. J'utilise le standard C ++ 11 et plus particulièrement libstdc ++. Eh bien, le std::regexsupport n’est pas complet . Bien sûr, il compile mais il jette une exception dans le sens où il s’agit d’une erreur commise par le programmeur. Mais c'est un manque de mise en œuvre. Alors voici comment je l'ai résolu. Installez les regex de Boost, liez-les. Ensuite, je fais ce qui suit pour que, quand libstdc ++ l’a entièrement implémentée, je n’ai plus qu’à supprimer ce bloc et le code reste le même:

namespace std
{
    using boost::regex;
    using boost::regex_error;
    using boost::regex_replace;
    using boost::regex_search;
    using boost::regex_match;
    using boost::smatch;
    namespace regex_constants = boost::regex_constants;  
}

Je ne dirai pas si c'est une mauvaise idée ou non. Je ferai cependant valoir que cela garde la propreté pour mon projet et le rend en même temps spécifique: Vrai, je dois utiliser Boost MAIS je l’utilise comme la libstdc ++ l’aura éventuellement. Oui, démarrer votre propre projet et commencer par une norme (...) au tout début contribue énormément à la maintenance, au développement et à tout ce qui est impliqué dans le projet!

Modifier:
Maintenant que j'ai le temps, juste pour clarifier quelque chose. Je ne pense pas réellement que ce soit une bonne idée d'utiliser un nom de classe / quoi que ce soit dans le TSL délibérément et plus spécifiquement à la place de. La chaîne est l'exception (ignorez le premier, ci-dessus, ou la deuxième ici, jeu de mots si vous le devez) pour moi car je n'aimais pas l'idée de 'String'. Dans l’état actuel des choses, je suis toujours très partial envers le C et contre le C ++. C’est un bon exercice et un bon moyen de me faire apprendre beaucoup de choses, c’est une bonne partie de ce que j’ai travaillé (c’est un bon exercice et un bon moyen de me faire a) apprendre une autre langue et b. moins fermé, moins arrogant, plus acceptant). Mais ce qui est utile, c’est ce que certains ont déjà suggéré: j’utilise bien la liste (elle est assez générique, n’est-ce pas?),trier (même chose) pour en nommer deux qui provoqueraient un conflit de noms si je devais le faireusing namespace std;et dans ce but, je préfère être spécifique, maîtriser le contrôle et savoir que si je le destine à être l’usage standard, je devrai le préciser. En termes simples: pas de supposition autorisée.

Et pour ce qui est de faire de la regex de Boost std. Je le fais pour une intégration future et - encore une fois, je reconnais pleinement que c'est un préjugé - je ne pense pas que ce soit aussi moche que boost::regex:: ...ça. En effet, c'est autre chose pour moi. Il y a beaucoup de choses en C ++ que je n'ai pas encore complètement acceptées dans les styles et les méthodes (un autre exemple: les modèles variadiques par rapport aux arguments variables [même si je reconnais que les modèles variadiques sont très très utiles!]). Même ceux que j’accepte, c’était difficile et j’ai toujours des problèmes avec eux.


  1. vous devez être capable de lire du code écrit par des personnes qui ont un style différent et des opinions de meilleures pratiques que vous.

  2. Si vous utilisez uniquement cout, personne ne s'embrouille. Mais lorsque vous avez beaucoup d'espaces de noms qui volent et que vous voyez cette classe et que vous n'êtes pas tout à fait sûr de ce que ça fait, le fait d'avoir un espace de noms explicite agit comme un commentaire. Vous pouvez voir à première vue, "oh, ceci est une opération de système de fichiers" ou "c'est faire des trucs de réseau".


Je considère aussi que c'est une mauvaise pratique. Pourquoi? Un jour, j’ai pensé que la fonction d’un espace de noms consistait à diviser des éléments; je ne devais donc pas gâcher le tout en jetant tout dans un seul sac. Cependant, si j'utilise souvent 'cout' et 'cin', j'écris: using std::cout; using std::cin; using std::cout; using std::cin; dans le fichier cpp (jamais dans le fichier d'en-tête car il se propage avec #include ). Je pense que personne digne de ce nom ne nommera jamais un cout ou un film. ;)


Ne l'utilisez pas globalement

Il est considéré comme "mauvais" uniquement lorsqu'il est utilisé globalement . Parce que:

  • Vous encombrez l'espace de noms que vous programmez.
  • Les lecteurs auront du mal à voir d'où provient un identifiant particulier, lorsque vous en utilisez beaucoup en using namespace xyz .
  • Ce qui est vrai pour les autres lecteurs de votre code source est encore plus vrai pour le lecteur le plus fréquent: vous-même. Revenez dans un an ou deux et jetez un coup d'œil ...
  • Si vous ne parlez que d' using namespace std vous risquez de ne pas être au courant de tout ce que vous récupérez - et lorsque vous ajoutez un autre #include ou passez à une nouvelle révision C ++, vous risquez d'obtenir des conflits de noms que vous ignoriez.

Vous pouvez l'utiliser localement

Allez-y et utilisez-le localement (presque) librement. Ceci, bien sûr, vous empêche de répéter std:: - et la répétition est également mauvaise.

Un idiome pour l'utiliser localement

En C ++ 03, il existait un idiome, le code général, pour implémenter une fonction de swap pour vos classes. Il a été suggéré que vous using namespace std réellement un using namespace std local en using namespace std - ou au moins en using std::swap :

class Thing {
    int    value_;
    Child  child_;
public:
    // ...
    friend void swap(Thing &a, Thing &b);
};
void swap(Thing &a, Thing &b) {
    using namespace std;      // make `std::swap` available
    // swap all members
    swap(a.value_, b.value_); // `std::stwap(int, int)`
    swap(a.child_, b.child_); // `swap(Child&,Child&)` or `std::swap(...)`
}

Cela fait la magie suivante:

  • Le compilateur choisira std::swap pour value_ , c’est-à-dire que void std::swap(int, int) .
  • Si vous avez un void swap(Child&, Child&) surcharge void swap(Child&, Child&) implémenté, le compilateur le choisira.
  • Si vous ne surchargez pas le compilateur, il utilisera void std::swap(Child&,Child&) et tentera de le faire en remplaçant.

Avec C ++ 11, il n’ya plus de raison d’utiliser ce modèle. L'implémentation de std::swap été modifiée pour rechercher une surcharge potentielle et la choisir.


Je ne pense pas que ce soit nécessairement une mauvaise pratique dans toutes les conditions, mais vous devez faire attention lorsque vous l'utilisez. Si vous écrivez une bibliothèque, vous devriez probablement utiliser les opérateurs de résolution de portée avec l'espace de noms pour empêcher votre bibliothèque de se heurter à d'autres bibliothèques. Pour le code de niveau d'application, je ne vois rien de mal à cela.


Il ne faut pas utiliser la directive using au niveau global, en particulier dans les en-têtes. Cependant, il y a des situations où cela convient même dans un fichier d'en-tête:

template <typename FloatType> inline
FloatType compute_something(FloatType x)
{
    using namespace std; //no problem since scope is limited
    return exp(x) * (sin(x) - cos(x * 2) + sin(x * 3) - cos(x * 4));
}

C'est mieux que la qualification explicite ( std::sin , std::cos ...), car elle est plus courte et permet de travailler avec des types à virgule flottante définis par l'utilisateur (via Argument Dependent Lookup).


"Pourquoi utiliser 'namespace std;' considéré comme une mauvaise pratique en C ++? "

Je le répète: pourquoi la saisie de 5 caractères supplémentaires est-elle considérée comme fastidieuse?

Par exemple, en écrivant un logiciel numérique, pourquoi devrais-je même envisager de polluer mon espace de noms global en coupant le "std :: vecteur" général en "vecteur" alors que "vecteur" est l'un des concepts les plus importants du domaine problématique?


Cela dépend de l'endroit où il se trouve. S'il s'agit d'un en-tête commun, vous diminuez la valeur de l'espace de noms en le fusionnant dans l'espace de noms global. Gardez à l'esprit, cela pourrait être une manière élégante de créer des modules globaux.


Un exemple où namespace std génère une erreur de compilation en raison de l'ambiguïté de count, qui est également une fonction de la bibliothèque d'algorithmes.

#include <iostream>

using namespace std;

int count = 1;
int main() {
    cout<<count<<endl;
}

Tout est question de gestion de la complexité. En utilisant l’espace de noms, vous obtiendrez des choses que vous ne voudrez pas, ce qui rendra probablement plus difficile le débogage (je dis peut-être). Utiliser std :: partout est plus difficile à lire (plus de texte et tout ça).

Horses for Courses - gérez votre complexité comme vous le pouvez et si vous vous en sentez capable.


Je suis d'accord avec tout ce que Greg a écrit , mais j'aimerais ajouter: Cela peut même être pire que ce que Greg a dit!

Library Foo 2.0 pourrait introduire une fonction, Quux() , qui correspond sans équivoque à certains de vos appels à Quux() celle du code bar::Quux() appelé par votre code depuis des années. Ensuite, votre code est toujours compilé , mais il appelle en silence la mauvaise fonction et fait dieu sait quoi. C'est à peu près aussi mauvais que les choses peuvent devenir.

Gardez à l’esprit que l’espace de noms std contient une multitude d’identificateurs, dont beaucoup sont très courants (penser list , sort , string , iterator , etc.) et susceptibles d’apparaître dans un autre code.

Si vous considérez cela comme improbable: une question a été posée ici sur , où cela se passait exactement (fonction incorrecte appelée en raison de l'absence de std:: prefix) environ un an et demi après avoir donné cette réponse. Here un autre exemple plus récent d'une telle question. C'est donc un réel problème.

Voici un autre point de données: il y a de nombreuses années, je trouvais aussi ennuyeux de devoir préfixer tout le contenu de la bibliothèque standard avec std:: . Ensuite, j'ai travaillé dans un projet où il avait été décidé au début d'interdire les directives et les déclarations, à l'exception des portées de fonction. Devine quoi? La plupart d’entre nous ont mis très peu de temps à s’habituer à l’écriture du préfixe et, au bout de quelques semaines, la plupart d’entre nous ont même convenu que cela rendait le code plus lisible . Il y a une raison à cela: que vous préfériez une prose plus courte ou plus longue est subjectif, mais les préfixes ajoutent objectivement de la clarté au code. Non seulement le compilateur, mais vous aussi, trouvez plus facile de savoir à quel identificateur il est fait référence.

En une décennie, ce projet a atteint plusieurs millions de lignes de code. Étant donné que ces discussions reviennent encore et encore, j’étais une fois curieux de savoir combien de fois la fonction (autorisée) utilisée était réellement utilisée dans le projet. J'ai grillé les sources pour cela et n'ai trouvé qu'une ou deux douzaines d'endroits où il était utilisé. Pour moi, cela indique que, une fois essayés, les développeurs ne trouvent pas assez std:: douloureux pour employer des directives, même une fois par 100 kLoC, même s’il était autorisé à l’utiliser.

Conclusion: le préfixe explicite de tout ne fait pas de mal, il faut très peu de temps pour s’y habituer et a des avantages objectifs. En particulier, cela rend le code plus facile à interpréter par le compilateur et les lecteurs humains - et cela devrait probablement être l'objectif principal lors de l'écriture de code.


Utiliser plusieurs espaces de noms en même temps est évidemment une recette pour un désastre, mais utiliser JUST namespace std et seulement namespace std n'est pas une grosse affaire à mon avis car la redéfinition ne peut se produire que par votre propre code ...

Il suffit donc de les considérer comme des noms réservés tels que "int" ou "classe" et c’est tout.

Les gens devraient cesser d'être si anales à ce sujet. Votre professeur avait raison depuis le début. Utilisez simplement UN espace de noms; c'est tout l'intérêt d'utiliser les espaces de noms en premier lieu. Vous n'êtes pas censé en utiliser plus d'un à la fois. À moins que ce ne soit le vôtre. Encore une fois, la redéfinition ne se produira pas.


Pour répondre à votre question, j’envisage la situation de manière pratique: beaucoup de programmeurs (pas tous) invoquent namespace std. Par conséquent, on devrait avoir l’habitude de NE PAS utiliser des choses qui empiètent ou utilisent les mêmes noms que ce qui est dans l’espace de noms std. C’est beaucoup, mais pas tellement comparé au nombre de mots cohérents et de pseudonymes possibles que l’on peut trouver à proprement parler.

Je veux dire vraiment ... dire "ne comptez pas sur sa présence", c'est simplement vous préparer à compter sur elle pour ne PAS être présente. Vous aurez constamment des problèmes pour emprunter des extraits de code et les réparer en permanence. Gardez simplement vos contenus définis et empruntés dans une portée limitée comme ils devraient être et soyez TRÈS économe avec les globals (honnêtement, les globals devraient presque toujours être un dernier recours pour les besoins de "compiler maintenant, plus tard". Vraiment, je pense que votre professeur vous a mal conseillé, car utiliser std fonctionnera à la fois pour "cout" et "std :: cout" mais NE PAS utiliser std ne fonctionnera que pour "std :: cout". Vous ne serez pas toujours assez chanceux pour écrire votre propre code.

REMARQUE: Ne vous concentrez pas trop sur les problèmes d'efficacité avant d'en apprendre un peu plus sur le fonctionnement des compilateurs. Avec un peu d'expérience en codage, vous n'avez pas besoin d'en apprendre beaucoup sur eux avant de réaliser à quel point ils sont capables de généraliser un bon code en quelque chose de simple. Aussi simple que si vous aviez tout écrit en C. Un bon code est aussi complexe qu'il le faut.


Considérer

// myHeader.h
#include <sstream>
using namespace std;


// someoneElses.cpp/h
#include "myHeader.h"

class stringstream {  // uh oh
};

Notez que ceci est un exemple simple. Si vous avez des fichiers avec 20 inclusions et d'autres importations, vous aurez une tonne de dépendances à parcourir pour résoudre le problème. Le pire, c’est que vous pouvez obtenir des erreurs non liées dans d’autres modules en fonction des définitions en conflit.

Ce n'est pas horrible, mais vous éviterez des maux de tête en ne l'utilisant pas dans les fichiers d'en-tête ou dans l'espace de noms global. C'est probablement bien de le faire dans des portées très limitées, mais je n'ai jamais eu de problème à taper les 5 caractères supplémentaires pour clarifier la provenance de mes fonctions.


Un exemple concret pour clarifier la préoccupation. Imaginez que vous ayez deux bibliothèques, foo et bar, chacune avec son propre espace de noms:

namespace foo {
    void a(float) { /* does something */ }
}

namespace bar {
    ...
}

Maintenant, supposons que vous utilisiez foo et bar ensemble dans votre propre programme comme suit:

using namespace foo;
using namespace bar;

void main() {
    a(42);
}

À ce stade, tout va bien. Lorsque vous exécutez votre programme, il "fait quelque chose". Mais plus tard, vous mettez à jour la barre et disons que cela a changé pour ressembler à ceci:

namespace bar {
    void a(float) { /* does something completely different */ }
}

À ce stade, vous obtiendrez une erreur de compilation:

using namespace foo;
using namespace bar;

void main() {
    a(42);  // error: call to 'a' is ambiguous, should be foo::a(42)
}

Vous devrez donc effectuer des travaux de maintenance pour clarifier ce que vous voulez dire (c. foo::a-à-d.). Ce n'est probablement pas souhaitable, mais heureusement, c'est assez facile (il suffit d'ajouter foo::devant tous les appels à acela que le compilateur est ambigu).

Mais imaginons un scénario alternatif dans lequel bar a plutôt changé pour ressembler à ceci:

namespace bar {
    void a(int) { /* does something completely different */ }
}

À ce stade, votre appel à a(42)soudainement se lie à bar::aau lieu de foo::aet au lieu de faire «quelque chose», il fait «quelque chose de complètement différent». Aucun avertissement du compilateur ou quoi que ce soit. Votre programme commence silencieusement à faire quelque chose de complètement différent d’avant.

Lorsque vous utilisez un espace de noms, vous vous exposez à un tel scénario. C'est pourquoi les utilisateurs ne sont pas à l'aise avec les espaces de noms. Plus le nombre d'éléments présents dans un espace de noms est élevé, plus le risque de conflit est grand. Par conséquent, les utilisateurs risquent d'être encore plus mal à l'aise d'utiliser l'espace de noms std (en raison du nombre d'éléments contenus dans cet espace de noms) que d'autres espaces de noms.

En fin de compte, il s’agit d’un compromis entre l’inscriptibilité, la fiabilité et la maintenabilité. La lisibilité peut aussi en tenir compte, mais je pouvais voir les arguments en ce sens. Normalement, je dirais que la fiabilité et la maintenabilité sont plus importantes, mais dans ce cas, vous devrez toujours payer le coût d'écriture pour un impact relativement rare en termes de fiabilité / maintenabilité. Le «meilleur» compromis déterminera votre projet et vos priorités.


Un espace de noms est une portée nommée. Les espaces de noms sont utilisés pour regrouper les déclarations associées et pour séparer les éléments séparés. Par exemple, deux bibliothèques développées séparément peuvent utiliser le même nom pour faire référence à des éléments différents, mais un utilisateur peut toujours utiliser les deux:

namespace Mylib{
    template<class T> class Stack{ /* ... */ };
    / / ...
}
namespace Yourlib{
    class Stack{ /* ... */ };
    / / ...
}
void f(int max) {
    Mylib: :Stack<int> s1(max) ; / / use my stack
    Yourlib: :Stack s2(max) ; / / use your stack
    / / ...
}

La répétition d'un nom d'espace de noms peut être une distraction pour les lecteurs et les rédacteurs. Par conséquent, il est possible d'indiquer que les noms d'un espace de noms particulier sont disponibles sans qualification explicite. Par exemple:

void f(int max) {
    using namespace Mylib; / / make names from Mylib accessible
    Stack<int> s1(max) ; / / use my stack
    Yourlib: :Stack s2(max) ; / / use your stack
    / / ...
}

Les espaces de noms constituent un outil puissant pour la gestion de différentes bibliothèques et de différentes versions de code. En particulier, ils offrent au programmeur des alternatives sur la manière explicite de faire référence à un nom non local.

Source: Présentation du langage de programmation C ++ par Bjarne Stroustrup


Les programmeurs expérimentés utilisent ce qui résout leurs problèmes et évitent tout ce qui crée de nouveaux problèmes, et ils évitent les directives using au niveau du fichier d'en-tête pour cette raison exacte.

Les programmeurs expérimentés essaient également d'éviter la qualification complète des noms dans leurs fichiers sources. Une raison mineure à cela est qu’il n’est pas élégant d’écrire plus de code quand moins de code suffit, sauf s’il ya de bonnes raisons . Une des principales raisons est la désactivation de la recherche dépendante de l’argument (ADL).

Quelles sont ces bonnes raisons ? Parfois, les programmeurs veulent explicitement désactiver ADL, d'autres fois, ils veulent être sans ambiguïté.

Donc, ce qui suit est OK:

  1. Directives-utilisateur et déclarations-d'utilisation au niveau des fonctions dans les implémentations des fonctions
  2. Utilisation de déclarations au niveau du fichier source dans les fichiers source
  3. (Parfois) directives-utilisation au niveau du fichier source




c++-faq