Création d'un espace de noms C ++ dans l'en-tête et la source (cpp)

88

Y a-t-il une différence entre l'encapsulation à la fois du contenu de l'en-tête et du fichier cpp dans un espace de noms ou l'encapsulation uniquement du contenu de l'en-tête et l' utilisation de l'espace de noms dans le fichier cpp?

Par différence, j'entends toute sorte de pénalité de performance ou une sémantique légèrement différente qui peut causer des problèmes ou tout ce dont je dois être conscient.

Exemple:

// header
namespace X
{
  class Foo
  {
  public:
    void TheFunc();
  };
}

// cpp
namespace X
{
  void Foo::TheFunc()
  {
    return;
  }
}

CONTRE

// header
namespace X
{
  class Foo
  {
  public:
    void TheFunc();
  };
}

// cpp
using namespace X;
{
  void Foo::TheFunc()
  {
    return;
  }
} 

S'il n'y a pas de différence, quelle est la forme préférée et pourquoi?

liens77
la source

Réponses:

37

L'espace de noms est juste un moyen de modifier la signature de la fonction afin qu'elle ne soit pas en conflit. Certains préfèrent la première façon et d'autres préfèrent la deuxième version. Les deux versions n'ont aucun effet sur les performances de compilation. Notez que les espaces de noms ne sont qu'une entité de compilation.

Le seul problème qui se pose avec l'utilisation de l'espace de noms est lorsque nous avons les mêmes noms d'espaces de noms imbriqués (ie) X::X::Foo. Cela crée plus de confusion avec ou sans l'utilisation de mots-clés.

vprajan
la source
55

La différence entre «namespace X» et «using namespace X» est que dans le premier, toutes les nouvelles déclarations seront sous l'espace de nom alors que dans le second ce ne sera pas le cas.

Dans votre exemple, il n'y a pas de nouvelle déclaration - donc pas de différence donc pas de méthode préférée.

Roee Gavirel
la source
Cela dépend du projet et du style. Il existe souvent un espace de noms principal pour une charge de fichiers dans un module, et le second style a du sens.
Nicholas Wilson
8

Il n'y a pas de pénalités de performance, car le résultat pourrait être le même, mais placer votre Foodans un espace de noms introduit implicitement une ambiguïté au cas où vous auriez des Foos dans différents espaces de noms. Vous pouvez en effet obtenir votre code fubar. Je recommanderais d'éviter d'utiliser usingà cette fin.

Et vous avez un égaré {après using namespace;-)

Michael Krelin - hacker
la source
Je n'appellerais pas cela errant, car cela correspond à la clôture }à la toute fin. Cependant, j'appellerais cette paire d'accolades redondante;)
blubberdiblub
@blubberdiblub, la question a été modifiée, si vous avez coché la version originale, vous voulez l' appeler ;-) égarent
Michael Krelin - pirate informatique
1

Si le second compile également, il ne devrait y avoir aucune différence. Les espaces de noms sont traités au moment de la compilation et ne doivent pas affecter les actions d'exécution.

Mais pour les problèmes de conception, la seconde est horrible. Même s'il compile (pas sûr), cela n'a aucun sens.

Holgac
la source
1
Je ne pense pas que ça compile, mais pas parce qu'il y a une différence, mais parce qu'il y a un égaré {;-)
Michael Krelin - hacker
La différence est que Foo :: TheFunc () est déclaré dans l'espace de noms global, alors qu'il est défini dans l'espace de noms X.
bert-jan
1

Le Foo :: TheFunc () n'est pas dans l'espace de noms correct dans le VS-case. Utilisez 'void X :: Foo :: TheFunc () {}' pour implémenter la fonction dans l'espace de noms correct (X).

bert-jan
la source
La question est un peu ancienne, mais savez-vous quelles en sont les conséquences? ie rencontrerez-vous des problèmes avec la façon dont son cas VS déclare les fonctions dans l'espace de noms, mais les définit en dehors de celui-ci?
Adam Goodwin
1

Dans le cas où vous n'emballez que le contenu .h, vous devez écrire en utilisant l'espace de noms ... dans le fichier cpp sinon vous travaillez à chaque fois sur l'espace de noms valide. Normalement, vous encapsulez les fichiers .cpp et .h, sinon vous risquez d'utiliser des objets d'un autre espace de noms, ce qui peut générer beaucoup de problèmes.

AlexTheo
la source
0

Je pense que la bonne chose à faire ici est d'utiliser un espace de noms pour la portée.

namespace catagory
{
    enum status
    {
      none,
      active,
      paused
    }
};

void func()
{
    catagory::status status;
    status = category::active;
}
Kjetil Hvalstrand
la source
0

Si vous essayez d'utiliser des variables de l'une à l'autre, je vous recommande de les externaliser, puis de les initialiser dans le fichier source comme suit:

// [.hh]
namespace example
{
   extern int a, b, c;
}
// [.cc]
// Include your header, then init the vars:
namespace example
{
   int a, b, c;
}
// Then in the function below, you can init them as what you want: 
void reference
{
    example::a = 0;
}

la source