Considérez une paire de deux fichiers source: un fichier de déclaration d'interface ( *.h
ou *.hpp
) et son fichier d'implémentation ( *.cpp
).
Laissez le *.h
fichier ressembler à ce qui suit:
namespace MyNamespace {
class MyClass {
public:
int foo();
};
}
J'ai vu deux pratiques différentes pour utiliser les espaces de noms dans les fichiers source:
*.cpp
montrant la pratique n ° 1:
#include "MyClass.h"
using namespace MyNamespace;
int MyClass::foo() { ... }
*.cpp
montrant la pratique n ° 2:
#include "MyClass.h"
namespace MyNamespace {
int MyClass::foo() { ... }
}
Ma question: y a-t-il des différences entre ces deux pratiques et l'une est-elle considérée comme meilleure que l'autre?
c++
namespaces
header-files
Nickolay
la source
la source
int MyNamespace::MyClass::foo() ...
.Réponses:
Du point de vue de la lisibilité du code, il est probablement préférable à mon avis d'utiliser la méthode n ° 2 pour cette raison:
Vous pouvez avoir
using
plusieurs espaces de noms à la fois, et tout objet ou fonction écrit sous cette ligne peut appartenir à l'un de ces espaces de noms (sauf conflits de noms). L'emballage du fichier entier dans unnamespace
bloc est plus explicite et vous permet de déclarer de nouvelles fonctions et variables qui appartiennent à cet espace de noms dans le fichier .cpp égalementla source
Le plus clair est l'option que vous n'avez pas montrée:
int MyNamespace::MyClass::foo() { // ... }
C'est aussi très verbeux; trop pour la plupart des gens. Puisqu'il
using namespace
s'agit d'une réception pour les conflits de noms, du moins d'après mon expérience, et qu'elle doit être évitée sauf dans des domaines et des endroits très limités, j'utilise généralement votre # 2.la source
Oui. # 1 et # 2 sont respectivement des exemples de directive using et de définition d'espace de noms . Ils sont effectivement les mêmes dans ce cas mais ont d'autres conséquences. Par exemple, si vous introduisez un nouvel identifiant à côté
MyClass::foo
, il aura une portée différente:#1:
using namespace MyNamespace; int x; // defines ::x
# 2:
namespace MyNamespace { int x; // defines MyNamespace::x }
# 1 Avantages: un peu plus concis; plus difficile d'introduire accidentellement quelque chose
MyNamespace
sans le vouloir. Inconvénients: peut extraire des identifiants existants sans le vouloir.# 2 Pour: il est plus clair que les définitions d'identifiants existants et les déclarations de nouveaux identifiants appartiennent à la fois
MyNamespace
. Inconvénients: il est plus facile d'introduire involontairement des identifiantsMyNamespace
.Une critique à la fois des # 1 et # 2 est qu'ils font référence à un espace de noms entier alors que vous ne vous souciez probablement que de la définition des membres de
MyNamespace::MyClass
. C'est lourd et cela communique mal l'intention.Une alternative possible à # 1 est une déclaration d'utilisation qui inclut uniquement l'identifiant qui vous intéresse:
#include "MyClass.h" using MyNamespace::MyClass; int MyClass::foo() { ... }
la source
Je voudrais également ajouter que si vous décidez pour une raison quelconque d'implémenter une spécialisation de modèle dans un fichier cpp et que vous comptez simplement sur
using namespace
vous, vous rencontrerez le problème suivant:// .h file namespace someNameSpace { template<typename T> class Demo { void foo(); }; } // .cpp file using namespace someNameSpace; template<typename T> void Demo<T>::foo(){} // this will produce // error: specialization of 'template<class T> void someNameSpace::Demo<T>::foo()' in different namespace [-fpermissive] template<> void Demo<int>::foo(){}
Sinon, si vous appliquez la méthode n ° 2, tout ira bien.
la source
Je voudrais ajouter une autre manière, en utilisant using-declaration :
#include "MyClass.h" using MyNamespace::MyClass; int MyClass::foo() { ... }
Cette façon vous évite de taper plusieurs fois le nom de l'espace de noms si la classe a de nombreuses fonctions
la source