"utiliser namespace" dans les en-têtes c++

dans tous nos cours de c++, Tous les enseignants mettent toujours using namespace std; juste après #include dans leurs fichiers .h . Cela me semble dangereux depuis lors en incluant cet en-tête dans un autre programme je vais faire importer l'Espace-nom dans mon programme, peut-être sans m'en rendre compte, avec l'intention ou en voulant (l'inclusion de l'en-tête peut être très profondément imbriquée).

donc ma question Est double: ai-je raison que using namespace ne devrait pas être utilisé dans les fichiers d'en-tête, et/ou est-il possible de l'annuler, quelque chose comme:

//header.h
using namespace std {
.
.
.
}

une question de plus dans le même ordre: un fichier d'en-tête #include devrait-il avoir tous les en-têtes dont il a besoin, seulement ceux qui sont nécessaires pour les définitions d'en-tête et laisser le .cpp fichier #include le reste, ou aucun et déclarer tout ce dont il a besoin comme extern ?

Le raisonnement derrière la question Est le même que ci-dessus: je ne vous voulez des surprises en incluant les fichiers .h .

aussi, si j'ai raison, est-ce une erreur courante? Je veux dire dans la programmation du monde réel et dans les projets "réels" là-bas.

Merci.

103
demandé sur baruch 2011-05-01 19:49:21

9 réponses

vous ne devriez certainement pas utiliser using namespace dans les en-têtes pour précisément la raison que vous dites, qu'il peut changer de façon inattendue la signification du code dans d'autres fichiers qui incluent cet en-tête. Il n'y a aucun moyen de défaire un using namespace ce qui est une autre raison pour laquelle il est si dangereux. En général, j'utilise simplement grep ou un truc du genre pour m'assurer que using namespace n'est pas appelé dans les en-têtes plutôt que d'essayer quelque chose de plus compliqué. Probablement les vérificateurs de code statique signalent cela aussi.

L'en-tête doit inclure juste les en-têtes qu'il doit compiler. Un moyen facile de faire respecter ceci est de toujours inclure l'en-tête propre à chaque fichier source comme première chose, avant tout autre en-tête. Alors le fichier source ne compilera pas si l'en-tête n'est pas autonome. Dans certains cas, par exemple en se référant à des classes implementation-detail dans une bibliothèque, vous pouvez utiliser des déclarations forward au lieu de #include parce que vous avez le contrôle total sur la définition d'un tel forward déclaré classe.

Je ne suis pas sûr que je l'appellerais commun, mais il apparaît certainement une fois de temps en temps, généralement écrit par de nouveaux programmeurs qui ne sont pas conscients des conséquences négatives. Typiquement, juste un peu d'éducation sur les risques prend soin de tous les problèmes car il est relativement simple à réparer.

94
répondu Mark B 2013-02-13 00:14:06

Article 59 de Sutter et Alexandrescu "C++ Normes de Codage: 101 Règles, des lignes Directrices et des Pratiques Exemplaires":

  1. N'écrivez pas les utilisations de namespace dans un fichier d'en-tête ou avant un #include. 108

les titres de toutes les lignes directrices sont à http://www.gotw.ca/publications/c++cs.htm , mais les détails sont incontournables pour les développeurs C++.

21
répondu Andy Thomas 2016-03-10 09:09:03

vous devez être prudent lorsque vous incluez des en-têtes à l'intérieur des en-têtes. Dans les grands projets, elle peut créer une chaîne de dépendances très enchevêtrée qui déclenche des reconstructions plus grandes/plus longues que celles qui étaient réellement nécessaires. Voir cet article et son suivi pour en savoir plus sur l'importance d'une bonne structure physique dans les projets C++.

vous ne devez inclure les en-têtes à l'intérieur d'un en-tête que lorsque cela est absolument nécessaire ( la définition complète d'une classe est nécessaire), et utilisez la déclaration forward partout où vous le pouvez (lorsque la classe est requise est un pointeur ou une référence).

en ce qui concerne les espaces de noms, j'ai tendance à utiliser la portée explicite de l'espace de noms dans Mes fichiers d'en-tête, et j'ai seulement mis un using namespace dans mes fichiers cpp.

12
répondu Mike O'Connor 2011-05-01 16:19:02

consultez les normes de codage du Goddard Space Flight Center (pour C et C++). Cela s'avère un peu plus difficile qu'avant - voir les réponses mises à jour aux questions SO:

la norme de codage C++ du GSFC dit:

§3.3.7 chaque fichier d'en-tête doit #include les fichiers qu'il doit compiler, plutôt que de forcer les utilisateurs à #include les fichiers nécessaires. #includes doit être limité à ce dont l'en-tête a besoin; l'autre #includes doit être placé dans le fichier source.

la première des questions de renvoi comprend maintenant une citation de la norme de codage C du CFSG et la justification, mais la substance finit par être la même.

6
répondu Jonathan Leffler 2017-05-23 11:54:16

vous avez raison, using namespace dans header est dangereux. Je ne sais pas un moyen de l'annuler. Il est facile de le détecter mais il suffit de rechercher using namespace dans les fichiers d'en-tête. Pour cette dernière raison, il est rare dans les projets réels. Des collègues plus expérimentés se plaindront bientôt si quelqu'un fait quelque chose comme ça.

dans les projets réels les gens essaient de minimiser la quantité de fichiers inclus, parce que moins vous incluez le plus rapide il compile. Un gain de temps de tout le monde. Toutefois, si le fichier d'en-tête suppose que quelque chose doit être inclus avant, puis il devrait comprendre elle-même. Sinon, les en-têtes ne sont pas autonomes.

5
répondu Öö Tiib 2011-05-01 17:15:01

vous avez raison. Et tout fichier ne doit inclure que les en-têtes nécessaires à ce fichier. Comme pour "faire les choses mal commun dans le monde réel des projets?"- oh, oui!

4
répondu Neil Butterworth 2011-05-01 15:52:33

comme toute chose dans la programmation, le pragmatisme devrait l'emporter sur le dogmatisme, IMO.

tant que vous prenez la décision à l'échelle du projet ("Notre projet utilise largement STL, et nous ne voulons pas avoir à tout préparer avec std:."), Je ne vois pas le problème avec lui. La seule chose que vous risquez, ce sont les collisions de noms, Après tout, et avec L'ubiquité de STL, il est peu probable que ce soit un problème.

d'autre part, s'il s'agit d'une décision d'un développeur dans un seul en-tête (non privé) - fichier, je peux voir comment il générerait la confusion parmi l'équipe et devrait être évitée.

3
répondu ijprest 2011-05-01 16:29:36

je crois que vous pouvez utiliser 'using' dans les en-têtes C++ en toute sécurité si vous écrivez vos déclarations dans un espace de noms imbriqué comme ceci:

namespace DECLARATIONS_WITH_NAMESPACES_USED_INCLUDED
{
    /*using statements*/

    namespace DECLARATIONS_WITH_NO_NAMESPACES_USED_INCLUDED
    {
        /*declarations*/
    }
}

using namespace DECLARATIONS_WITH_NAMESPACES_USED_INCLUDED::DECLARATIONS_WITH_NO_NAMESPACES_USED_INCLUDED;

cela ne devrait inclure que les choses déclarées dans "DECLARATIONS_WITH_NO_NAMESPACES_USED_INCLUSES" sans les espaces de noms utilisés. Je l'ai testé sur mingw64 compilateur.

2
répondu AnArrayOfFunctions 2014-11-16 17:47:51

quant à "Est-il un moyen pour annuler [ using déclaration]?"

je pense qu'il est utile de souligner que les déclarations using sont affectées par le champ d'application.

#include <vector>

{   // begin a new scope with {
    using namespace std;
    vector myVector;  // std::vector is used
}   // end the scope with }

vector myOtherVector;   // error vector undefined
std::vector mySTDVector // no error std::vector is fully qualified

donc effectivement Oui. En limitant le champ d'application de la déclaration using , son effet ne dure qu'à l'intérieur de ce champ d'application; il est "Annulé" lorsque ce champ d'application prend fin.

lorsque la déclaration using est déclarée dans un dossier en dehors de toute autre portée, il a fichier-champ d'application et affecte tout dans ce fichier.

dans le cas d'un fichier d'en-tête, si la déclaration using se trouve à file-scope ceci s'étendra à la portée de tout fichier dans lequel l'en-tête est inclus.

2
répondu YoungJohn 2016-02-26 18:27:18