Je suis passé de C ++ à Java et C # et je pense que l'utilisation des espaces de noms / packages est bien meilleure ici (bien structurée). Ensuite, je suis revenu au C ++ et j'ai essayé d'utiliser les espaces de noms de la même manière, mais la syntaxe requise est horrible dans le fichier d'en-tête.
namespace MyCompany
{
namespace MyModule
{
namespace MyModulePart //e.g. Input
{
namespace MySubModulePart
{
namespace ...
{
public class MyClass
Ce qui suit me semble également étrange (pour éviter le retrait profond):
namespace MyCompany
{
namespace MyModule
{
namespace MyModulePart //e.g. Input
{
namespace MySubModulePart
{
namespace ...
{
public class MyClass
{
Existe-t-il un moyen plus court d'exprimer ce qui précède? Il me manque quelque chose comme
namespace MyCompany::MyModule::MyModulePart::...
{
public class MyClass
Mettre à jour
Ok, certains disent que le concept d'utilisation en Java / C # et C ++ est différent. Vraiment? Je pense que le chargement de classe (dynamique) n'est pas le seul but des espaces de noms (c'est une perspective raisonnée très technique). Pourquoi ne pas l'utiliser pour une lisibilité et une structuration, par exemple pensez à "IntelliSense".
Actuellement, il n'y a pas de logique / colle entre un espace de noms et ce que vous pouvez y trouver. Java et C # font cela beaucoup mieux ... Pourquoi inclure <iostream>
et avoir un espace de noms std
? Ok, si vous dites que la logique doit reposer sur l'en-tête à inclure, pourquoi le #include n'utilise-t-il pas une syntaxe conviviale "IntelliSense" comme #include <std::io::stream>
ou<std/io/stream>
? Je pense que la structuration manquante dans les bibliothèques par défaut est une faiblesse de C ++ par rapport à Java / C #.
Si l'unicité des conflits avides est un point (qui est également un point de C # et Java), une bonne idée est d'utiliser le nom du projet ou le nom de l'entreprise comme espace de noms, ne pensez-vous pas?
D'une part, on dit que C ++ est le plus flexible ... mais tout le monde a dit "ne fais pas ça"? Il me semble que le C ++ peut faire beaucoup de choses mais a une syntaxe horrible même pour les choses les plus simples dans de nombreux cas par rapport au C #.
Mise à jour 2
La plupart des utilisateurs disent qu'il est absurde de créer une imbrication plus profonde que deux niveaux. Ok, alors qu'en est-il des espaces de noms Windows :: UI :: Xaml et Windows :: UI :: Xaml :: Controls :: Primitives dans le développement Win8? Je pense que l'utilisation des espaces de noms par Microsoft a du sens et qu'elle est en effet plus profonde que 2 niveaux. Je pense que les bibliothèques / projets plus importants ont besoin d'une imbrication plus profonde (je déteste les noms de classe comme ExtraLongClassNameBecauseEveryThingIsInTheSameNameSpace ... alors vous pouvez tout mettre dans l'espace de noms global aussi.)
Mise à jour 3 - Conclusion
La plupart disent "ne le faites pas", mais ... même le boost a une imbrication plus profonde qu'un ou deux niveaux. Oui, c'est une bibliothèque mais: Si vous voulez du code réutilisable - traitez votre propre code comme une bibliothèque que vous donneriez à quelqu'un d'autre. J'utilise également une imbrication plus profonde à des fins de découverte à l'aide d'espaces de noms.
la source
namespace
mot-clé?Réponses:
C ++ 17 pourrait simplifier la définition d'espaces de noms imbriqués:
est équivalent à
Voir (8) sur la page d'espace de noms sur cppreference:
http://en.cppreference.com/w/cpp/language/namespace
la source
/std:c++latest
/std:c++latest
dans Visual Studio 2015 et que vous utilisez également Boost, vous pouvez rencontrer des erreurs de compilation très mystiques lorsque vous incluez des en-têtes Boost. J'ai rencontré ce problème comme décrit dans cette questionPour éviter une indentation vraiment profonde, je le fais généralement de cette façon:
la source
clang-format
ne peut pas formater cela comme vous montrez clang.llvm.org/docs/ClangFormatStyleOptions.html (NamespaceIndentation)Je soutiens pleinement la réponse de Peterchen, mais je souhaite ajouter quelque chose qui répond à une autre partie de votre question.
La déclaration d'espaces de noms est l'un des très rares cas en C ++ où j'aime vraiment l'utilisation de
#define
s.Cela supprime également le besoin de commentaires près de l'accolade fermante de l'espace de noms (avez-vous déjà fait défiler vers le bas d'un gros fichier source et essayé d'ajouter / supprimer / équilibrer les accolades qui manquaient de commentaires sur quelle accolade ferme quelle portée? .).
Si vous voulez mettre toutes les déclarations d'espaces de noms sur une seule ligne, vous pouvez également le faire avec un peu de magie (assez moche) du préprocesseur:
Vous pouvez maintenant faire ceci:
Pour une imbrication à plus de trois niveaux, vous devrez ajouter des macros d'assistance jusqu'au nombre souhaité.
la source
#define
je suis assez impressionné par cette magie du préprocesseur ... seulement si je n'ai pas à ajouter de macros d'assistance supplémentaires pour une imbrication plus profonde ... eh bien, je ne vais pas l'utiliser de toute façon, donc .. .Les espaces de noms C ++ sont utilisés pour regrouper les interfaces, non pour diviser les composants ou exprimer la division politique.
La norme fait tout son possible pour interdire l'utilisation d'espaces de noms de type Java. Par exemple, les alias d'espaces de noms permettent d'utiliser facilement des noms d'espaces de noms longs ou profondément imbriqués.
Mais ce
namespace nsc {}
serait alors une erreur, car un espace de noms ne peut être défini qu'en utilisant son nom d'espace de noms d'origine . Essentiellement, la norme rend les choses faciles pour l' utilisateur d'une telle bibliothèque mais difficile pour l' implémenteur . Cela décourage les gens d'écrire de telles choses mais atténue les effets s'ils le font.Vous devez avoir un espace de noms par interface défini par un ensemble de classes et de fonctions associées. Des sous-interfaces internes ou facultatives peuvent entrer dans des espaces de noms imbriqués. Mais plus de deux niveaux de profondeur devraient être un signal d'alarme très grave.
Pensez à utiliser des caractères de soulignement et des préfixes d'identifiant lorsque l'
::
opérateur n'est pas nécessaire.la source
company::division
overcompany_division
?Non, et ne faites pas ça.
Le but des espaces de noms est principalement de résoudre les conflits dans l'espace de noms global.
Un objectif secondaire est l'abréviation locale des symboles; par exemple, une
UpdateUI
méthode complexe peut utiliser unusing namespace WndUI
pour utiliser des symboles plus courts.Je suis sur un projet 1.3MLoc, et les seuls espaces de noms dont nous disposons sont:
#import
et#include windows.h
)ModuleDetailHereBeTygers
espaces de noms dans les bibliothèques d'en-tête uniquement)Dans ce projet, les noms de classe, etc. utilisent un code «région» à deux ou trois lettres (par exemple
CDBNode
au lieu deDB::CNode
). Si vous préférez ce dernier, il y a de la place pour un deuxième niveau d'espaces de noms "publics", mais pas plus.Les énumérations spécifiques à une classe, etc. peuvent être membres de ces classes (même si je suis d'accord que ce n'est pas toujours bon, et il est parfois difficile de dire si vous devriez)
Il y a rarement besoin d'un espace de noms "entreprise" non plus, sauf si vous rencontrez de gros problèmes avec des bibliothèques tierces qui sont distribuées en tant que binaire, ne fournissent pas leur propre espace de noms et ne peuvent pas être facilement mises en un (par exemple, dans un binaire Distribution). Pourtant, dans mon expérience forçant les dans un espace de noms est beaucoup plus facile à faire.
[modifier] Selon la question de suivi de Stegi:
Désolé si je n'étais pas assez clair: deux niveaux ne sont pas une limite stricte, et plus n'est pas intrinsèquement mauvais. Je voulais juste souligner que vous en avez rarement besoin de plus de deux, d'après mon expérience, même sur une grande base de code. Une nidification plus profonde ou moins profonde est un compromis.
Maintenant, le cas de Microsoft est sans doute différent. Vraisemblablement une équipe beaucoup plus grande, et tout le code est une bibliothèque.
Je suppose que Microsoft imite ici le succès de la bibliothèque .NET, où les espaces de noms contribuent à la découvrabilité de la bibliothèque étendue. (.NET a environ 18000 types.)
Je suppose en outre qu'il existe un (ordre de grandeur de) symboles optimal dans un espace de noms. dire, 1 n'a pas de sens, 100 sons corrects, 10000 c'est clairement trop.
TL; DR: C'est un compromis, et nous n'avons pas de chiffres précis. Jouez prudemment, n'en faites pas trop dans aucune direction. Le "Ne fais pas ça" vient simplement du "Tu as des problèmes avec ça, j'aurais des problèmes avec ça, et je ne vois pas pourquoi tu en aurais besoin.".
la source
Constants
, puis créer des espaces de noms imbriqués avec des noms appropriés pour catégoriser les constantes; si nécessaire, j'utilise ensuite d'autres espaces de noms pour éviter les collisions de noms. CetConstants
espace de noms est lui-même contenu dans un espace de noms fourre-tout pour le code système du programme, avec un nom tel queSysData
. Cela crée un nom complet contenant trois ou quatre espaces de noms ( par exempleSysData::Constants::ErrorMessages
,SysData::Constants::Ailments::Bitflags
ouSysData::Defaults::Engine::TextSystem
).using
directive pour apporter les noms appropriés, minimisant ainsi la possibilité de conflits de noms. Je trouve que cela améliore la lisibilité et aide à documenter les dépendances de tout bloc de code donné. En dehors des constantes, j'ai tendance à essayer de le conserver dans deux espaces de noms si possible (tels queSysData::Exceptions
etSysData::Classes
).Voici une citation de la documentation Lzz (Lazy C ++):
Bien sûr la qualité des sources qui dépend de tels outils est discutable ... Je dirais que c'est plus une curiosité, montrer que la maladie de syntaxe induite par C ++ peut prendre plusieurs formes (j'ai la mienne aussi ...)
la source
Les deux normes (C ++ 2003 et C ++ 11) sont très explicites que le nom de l'espace de noms est un identifiant. Cela signifie que des en-têtes imbriqués explicites sont requis.
J'ai l'impression que ce n'est pas un gros problème de permettre de placer un identifiant qualifié en plus d'un simple nom de l'espace de noms, mais pour une raison quelconque, cela n'est pas autorisé.
la source
Vous pouvez utiliser cette syntaxe:
Notez que cette syntaxe est valide même en C ++ 98 et qu'elle est presque similaire à ce qui est maintenant disponible en C ++ 17 avec des définitions d'espaces de noms imbriqués .
Heureux sans nidification!
Sources:
la source
Cet article couvre assez bien le sujet: Papier d'espace de noms
Ce qui résume fondamentalement cela. Plus vos espaces de noms sont longs, plus il y a de chances que les gens utilisent le
using namespace
directive.Donc, en regardant le code suivant, vous pouvez voir un exemple où cela vous blessera:
Ce code se compilera bien, cependant, si vous décommentez la ligne,
//using namespace def;
l'espace de noms "testing" deviendra ambigu et vous aurez des conflits de noms. Cela signifie que votre base de code peut passer de stable à instable en incluant une bibliothèque tierce.En C #, même si vous deviez utiliser
using abc;
et queusing def;
le compilateur est capable de reconnaître celatesting::myClass
ou mêmemyClass
est seulement dans l'abc::testing
espace de noms, mais C ++ ne le reconnaîtra pas et il est détecté comme une collision.la source
Oui, vous devrez le faire comme
Cependant, vous essayez d'utiliser les espaces de noms d'une manière qu'ils ne sont pas censés être utilisés. Vérifiez cette question, vous la trouverez peut-être utile.
la source
[EDIT:]
Étant donné que les espaces de noms imbriqués c ++ 17 sont pris en charge en tant que fonctionnalité de langage standard ( https://en.wikipedia.org/wiki/C%2B%2B17 ). À partir de maintenant, cette fonctionnalité n'est pas prise en charge dans g ++ 8, mais elle peut être trouvée dans le compilateur in clang ++ 6.0.
[CONCLUSION:]
Utilisez
clang++6.0 -std=c++17
comme commande de compilation par défaut. Ensuite, tout devrait bien fonctionner - et vous pourrez compiler avecnamespace OuterNS::InnerNS1::InnerNS2 { ... }
dans vos fichiers.[RÉPONSE ORIGINALE:]
Puisque cette question est un peu ancienne, je suppose que vous avez évolué. Mais pour d'autres, qui cherchent encore une réponse, j'ai eu l'idée suivante:
(Puis-je faire une publicité pour Emacs ici :)?) Publier une image est beaucoup plus facile et plus lisible que de simplement poster du code. Je n'ai pas l'intention de fournir une réponse complète de tous les cas d'angle, je voulais simplement donner de l'inspiration. (Je supporte totalement C # et pense que dans de nombreux cas, C ++ devrait adopter certaines fonctionnalités de la POO, car C # est populaire principalement en raison de sa facilité d'utilisation comparée).
la source