2009-08-02 5 views
7

J'essaie de mettre en question mon propre exactitude de code sur l'exemple minimaliste suivant dans lequel un fichier d'en-tête soulève un identifiant dans l'espace de noms actuel.Correction de l'espace de noms

#include <string> 

namespace mine { 

    using std::string; // std::string lifted into mine 

    struct agent 
    { 
     string name; 
    }; 
} 

Ceci est une suggestion que j'ai fait récemment comme une autre alternative à l'utilisation d'un typedef:

#include <string> 

struct agent 
{ 
    private: 
     typedef std::string string; 
    public: 
     string name; 
}; 

Je considère la première option plus correcte car il utilise mon propre espace de noms et ceci est un pratique à laquelle on devrait s'habituer (celle de la création et de la gestion des espaces de nommage). En outre, puisque l'identificateur est levé à l'intérieur d'un espace de noms que je contrôle, cela en fait une approche sûre.

Cependant, j'ai des doutes. D'une part, une utilisation négligente de l'espace de noms mine, avec une directive using par exemple, mettra aussi std :: string en vue. Un autre problème est que j'expose trop std :: string. Peut-être même à des zones de l'espace de noms mine où ce n'est pas nécessaire ou souhaitable.

Il me semble plus correct de toujours travailler à la portée la plus basse possible et de travailler à partir de là. Exposer seulement l'absolument nécessaire. Le fait que je rende le typedef privé sur le deuxième exemple était exactement à cause de cela. Mais alors je ne suis pas mes propres conseils avec le deuxième exemple.

Mais d'autre part, mes préoccupations résultent de la fait que quelqu'un pourrait abuser de l'espace de noms mien:

using namespace mine; 

À première vue, nous savons que ce n'est pas un modèle d'utilisation correcte pour un espace de noms. Mais on ne peut nier qu'il y a des cas où cela peut être souhaitable. Selon vous, quelle est la première approche?

Répondre

8

j'aurais pensé la solution évidente est:

namespace mine { 
    struct agent 
    { 
     std::string name; 
    }; 
} 

Personnellement, je ne pas utiliser l'aide de directives dans les fichiers d'en-tête du tout. Dans les fichiers de mise en œuvre, certainement.

+0

Absolument! En tout cas, l'exemple sert les cas où l'auteur a trop de types à déclarer à l'intérieur d'une classe et souhaite simplifier leur frappe. J'ai senti que j'ai donné le mauvais conseil avec le premier exemple. Mais j'aimerais avoir quelques pensées, puisque std :: string est plutôt innocuos. –

+1

Je suppose que je ne suis pas clair sur ce que vous demandez vraiment. Mais j'observerais que dans les espaces de noms C++ ne sont pas des outils de conception, donc si vous rencontrez beaucoup de problèmes d'espace de noms, vous avez probablement trop d'espaces de noms. –

7

je fais normalement ceci:

// In header file: 

#include <string> 

namespace mine { 

    struct agent 
    { 
     std::string name; 
    }; 
} 

// In source file: 

using std::string; 

namespace mine { 
    // Code 
}  

De cette façon, vous n'avez pas d'écrire std :: encore et encore dans la mise en œuvre, mais vous éviter le problème des personnes qui utilisent vos têtes par inadvertance importateurs std :: symboles.

+0

Si "mine" définit des modèles, le fichier d'en-tête est le fichier source. –

1

que je fais habituellement ceci:

// In header file 
#include <string> 
namespace mine 
{ 
    namespace detail 
    { 
     using std::string; 

     struct agent 
     { 
      string name; 
     } 
    } 

    using detail::agent; 
} 

De cette façon, je ne dois pas continuer à taper std:: dans l'en-tête soit, mais quelqu'un peut encore faire using namespace mine; et non importer des noms de std.