IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

 C++ Discussion :

Question récurrente : Pourquoi ne pas utiliser 'using namespace std' ?


Sujet :

C++

  1. #1
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2019
    Messages
    2
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2019
    Messages : 2
    Points : 3
    Points
    3
    Par défaut Question récurrente : Pourquoi ne pas utiliser 'using namespace std' ?
    Je ne comprends pas l'interêt de répéter sans cesse dans mon code 'std::' devant chaque instruction de la bibliothèque standard.

    Pourquoi ne peut-on pas utiliser 'using namespace std' dans le main , tout simplement ?

    Merci pour votre aide..

  2. #2
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 612
    Points : 30 612
    Points
    30 612
    Par défaut
    Salut,
    Un peu d'histoire:
    Pour comprendre l'origine de cette directive qui pose souvent plus de problèmes qu'elle n'en résout, il faut savoir que les fonctionnalités de la bibliothèque standard n'ont été placées dans l'espace de noms std qu'avec la mise à jour de la norme effectuée en 1998.

    Mais, à cette époque, le langage existait déjà depuis une bonne dizaine d'années, si bien qu'il y avait déjà une très grande quantité de projets qui l'utilisaient, ce qui se traduisait déjà à l'époque par une quantité de code phénoménale.

    Il était, bien sur, hors de question d'obliger les développeurs à reprendre l'ensemble de leur code pour ajouter le préfixe std:: devant toutes les fonctionnalités de la bibliothèque standard qu'ils utilisaient, car cela aurait nécessité des heures de travail sur tous les projets.

    Il fallait donc trouver un moyen de faire en sorte que ces projets continuent à compiler correctement malgré le passage éventuel à une version "plus récente" du compilateur, et qui ne nécessite qu'"un minimum" de modifications du code existant.

    La directive using namespace n'a été créée que dans ce seul et unique but. Parce qu'il suffisait à l'époque de l'ajouter dans un fichier d'en-tête inclus partout (comme le fichier souvent nommé config.h) pour qu'elle puisse s'appliquer a priori dans n'importe quelle unité de compilation.

    Seulement, voilà: cela fait maintenant plus de vingt ans que les fonctionnalités de la bibliothèques standard sont regroupées dans l'espace de noms std. On peut donc difficilement estimer que le code que l'on écrit "de nos jours" ait la moindre chance de devoir être compilé avec un compilateur datant d'avant 1998

    Il n'y a donc aucun intérêt à utiliser cette directive de nos jours, d'autant plus qu'elle pose en définitive beaucoup plus de problèmes qu'elle n'en résout.

    Comprendre les espaces de noms
    Pour te permettre de comprendre l'intérêt, il faut déjà que tu comprenne celui des espaces de noms (namespaces en anglais).

    Pour faire simple, un espace de noms est une "boite de rangement" dans laquelle tu pourras placer les fonctionnalités qui "vont bien ensembles". Que ce soit pour toi-même ou pour le compilateur, cela va permettre de faire la différence entre des fonctionnalités qui portent le même nom, mais qui ont des usage sans doute totalement différents, parce qu'elles sont issues de "boites de rangement" différentes.

    Par exemple, la bibliothèque standard propose une classe (template) appelée std::vector, qui nous permet de gérer des tableaux d'éléments contigus en mémoire de maniière simple et sécurisante. Mais le terme vector en lui-même se traduit en français par "vecteur". Or, ce terme peut prendre des significations selon le domaine dans lequel on travaille:

    • En mathématique, par exemple, un vecteur représente une segment de droite orienté, comme un couple de points ou une translation qui doit être effectuée, et on peut effectuer des opérations mathématiques sur deux ou plusieurs vercteurs (certaines d'entre elles ayant pour résultat la création de matrices).
    • En médecine un "vecteur infectieux" ou un "vecteur de contagion" est un organisme (bactérie ou virus) susceptible de transmettre une infection ou une maladie aux gens.


    Le problème, c'est que, que l'on veuille parler du tableau de la bibliothèque standard, d'un vecteur au sens mathématique ou d'un vecteur d'infection, nous utiliserons le même terme en anglais: vector.

    Alors, imaginons que tu veuille créer un petit jeux avec différents éléments qui bougent à l'écran. Je te conseillerais sans doute de créer une classe (ou une structure) pour représenter la translation d'un objet et, comme j'ai l'habitude d'écrire mon code en anglais, je te conseillerais de l'appeler ... vector, et de placer cette structure dans un espace de noms dédié (que j'appellerais game pour l'occasion).

    Puis, comme il y a plusieurs éléments qui doivent être déplacés à chaque frame, je te conseillerais de regrouper les vecteurs dans un tableau, de manière à pouvoir appliquer la translation adéquate à chaque objet. Ce qui nous pousserait à créer une instance de... vector (les tableaux de la bibliothèque standard) de... vector (les vecteurs que l'on a mis au point).

    Au final, nous serions sans doute face à un code qui pourrait se réduire à quelque chose comme
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    #include <vector>
    namespace game{
    struct vector{
        int x;
        int y
    };
    } // namespace game
    int main(){
        std::vector<Game::vector> translations;
        /* ... */
    }
    Tant que tant que tu n'utiliseras pas la directive using namespace; tu n'auras pas de problème, car, le fait d'utiliser les noms pleinement qualifiés (std::vector et game::vector) évite tout risque de confusion pour le compilateur: il sait qu'il doit aller chercher dans l'espace de noms std pour trouver le tableau et dans l'espace de noms game pour trouver le vecteur mathématique.

    Oui, mais, qu'est ce que ca peut être emmerdant de devoir écrire à chaque fois std:: ou game:: !!! On va se simplifier la vie, et utiliser une directive using namespace std; pour pouvoir accéder directement aux tableaux par leur nom simplifié et, tant qu'à faire, on va utiliser une directive using namespace game; pour pouvoir accéder aux vecteurs de mathématiques; ce qui nous donnera un code proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    #include <vector>
    using namespace std;
    namespace game{
    /* rajoutons de l'ambiguité, car on peut traiter
     * n"importe quel type de valeur numérique
     */
    template <typename T>
    struct vector{
       /* par facilité */
       using value_type = T;
        value_type x;
        value_type y
    };
    } // namespace game
    using namespace game;
    int main(){
        vector<vector<double>> translations;
        /* ... */
    }
    C'est beaucoup plus simple, non

    Sauf que, du coup, on crée une ambiguité: le compilateur se trouve face à deux classes qui portent le même nom, mais qui sont définie de manière totalement différente. Et il ne se gène pas pour le dire, car, si on essaye de compiler ce code avec gcc, nous obtenons un message ressemblant à
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    g++ main.cpp
    main.cpp:7:15: error: expected nested-name-specifier before 'value_type'
             using value_type;
                   ^~~~~~~~~~
    main.cpp:8:9: error: 'value_type' does not name a type
             value_type x;
             ^~~~~~~~~~
    main.cpp:9:9: error: 'value_type' does not name a type
             value_type y;
             ^~~~~~~~~~
    main.cpp: In function 'int main()':
    main.cpp:15:5: error: reference to 'vector' is ambiguous
         vector<vector<double>> translations;
         ^~~~~~
    main.cpp:6:12: note: candidates are: 'template<class T> struct game::vector'
         struct vector{
                ^~~~~~
    In file included from D:/dev/mingw-8.1.0/x86_64/mingw64/lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++/vector:64,
                     from main.cpp:1:
    D:/dev/mingw-8.1.0/x86_64/mingw64/lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++/bits/stl_vector.h:339:11: note:                 'template<class _Tp, class _Alloc> class std::vector'
         class vector : protected _Vector_base<_Tp, _Alloc>
               ^~~~~~
    main.cpp:15:12: error: reference to 'vector' is ambiguous
         vector<vector<double>> translations;
                ^~~~~~
    main.cpp:6:12: note: candidates are: 'template<class T> struct game::vector'
         struct vector{
                ^~~~~~
    In file included from D:/dev/mingw-8.1.0/x86_64/mingw64/lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++/vector:64,
                     from main.cpp:1:
    D:/dev/mingw-8.1.0/x86_64/mingw64/lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++/bits/stl_vector.h:339:11: note:                 'template<class _Tp, class _Alloc> class std::vector'
         class vector : protected _Vector_base<_Tp, _Alloc>
               ^~~~~~
    main.cpp:15:19: error: expected primary-expression before 'double'
         vector<vector<double>> translations;
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  3. #3
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2019
    Messages
    2
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2019
    Messages : 2
    Points : 3
    Points
    3
    Par défaut Merci encore..
    Encore merci pour partager vos connaissances.

    Vous avez très bien expliqué l'origine de la directive 'using namespace std', et je comprends parfaitement l'ambiguité de son utilisation aujourd'hui.

    Malheuresement beaucoup de sites continuent à alimenter cet dilemme.


    MERCI !!

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [PHP 5.3] pourquoi ne pas utiliser "break" dans une boucle
    Par ikuzar dans le forum Langage
    Réponses: 5
    Dernier message: 30/07/2012, 09h36
  2. [TeX][LaTeX] Pourquoi ne pas utiliser TeX ?
    Par Le Barde dans le forum Programmation (La)TeX avancée
    Réponses: 3
    Dernier message: 24/09/2007, 00h11
  3. Pourquoi ne pas utiliser Word, Excel, Powerpoint ?
    Par kisitomomotene dans le forum Autres outils décisionnels
    Réponses: 23
    Dernier message: 08/09/2006, 18h02

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo