web-dev-qa-db-fra.com

Conseils sur les espaces de noms C++

J'apprends juste moi-même les espaces de noms C++ (issus d'un arrière-plan C #) et je commence vraiment à penser que même avec tout ce que le C++ fait de mieux que la plupart des langages, les espaces de noms imbriqués n'en font pas partie!

Ai-je raison de penser que pour déclarer des espaces de nom imbriqués, je dois procéder comme suit: 

namespace tier1
{
    namespace tier2
    {
        namespace tier3
        {
            /* then start your normal code nesting */
        }
    }
}

Par opposition à: 

namespace tier1::tier2::tier3
{
}

à la C #?

Cela devient encore plus dément quand je dois transmettre, déclarer:

namespace tier1
{
    namespace tier2
    {
        namespace forward_declared_namespace
        {
            myType myVar; // forward declare
        }
        namespace tier3
        {
            /* then start your normal code nesting */
            class myClass
            {
                forward_declared_namespace::myType myMember;
            }
        }
    }
}

Gardant à l'esprit qu'un système typique que je développe consiste à:

MyCompany::MySolution::MyProject::System::[PossibleSections]::Type

Est-ce la raison pour laquelle vous n'avez pas tendance à utiliser beaucoup d'espaces de noms dans les exemples C++? Ou généralement uniquement des espaces de noms uniques (non imbriqués)?

METTRE À JOUR

Pour les personnes intéressées, c'est comme ça que j'ai fini s'attaquer à ce problème.

71
Adam Naylor

Les espaces de noms C++ n'étaient pas destinés à être un mécanisme de conception - ils servent simplement à empêcher les conflits de noms. Vous ne voulez vraiment pas ou n'avez pas besoin d'utiliser d'espaces de noms imbriqués dans 99,99% des situations.

La bibliothèque standard C++ est un bon exemple d'utilisation correcte des espaces de noms en C++. Tout dans cette assez grande bibliothèque est placé dans un seul espace de noms appelé std - il n’ya ni tentative ni besoin de diviser la bibliothèque en (par exemple) un espace de noms I/O, un conteneur, sous-espace de noms, etc.

L'outil de base pour la modélisation en C++ est la classe (et dans une certaine mesure le modèle), pas l'espace de nom. Si vous avez besoin d'imbrication, envisagez d'utiliser des classes imbriquées, qui présentent les avantages suivants par rapport aux espaces de noms:

  • ils ont des méthodes
  • ils peuvent contrôler l'accès
  • ils ne peuvent pas être rouverts

Cela dit, si vous souhaitez toujours utiliser les espaces de noms imbriqués, faites-le - il n’ya rien de mal techniquement à les utiliser de cette façon.

106
anon

Les espaces de noms C++ constituaient une amélioration considérable par rapport à l'offre précédente (c'est-à-dire aucun espace de noms). Les espaces de noms C # ont étendu le concept et ont fonctionné avec. Je vous conseillerais de conserver vos espaces de noms dans une structure simple et plate.

EDITEst-ce que vous conseillez cela en raison des lacunes que j'ai décrites ici?

Simplement "oui". Les espaces de noms C++ n'ont pas été conçus pour vous aider à partitionner votre logique et vos bibliothèques comme ils le font en C #.

Le but des espaces de noms C++ est d'arrêter le problème réel rencontré par les développeurs C, où ils rencontrent des conflits de nom lorsqu'ils utilisent deux bibliothèques tierces exportant le même nom de fonction. Les développeurs C ont eu diverses solutions de contournement, mais cela pourrait être une douleur sérieuse.

L'idée était que le fichier STL, etc., avait l'espace de noms std::, les bibliothèques fournies par "XYZ Corp" auraient un espace de noms xyz::, tandis que vous travaillez pour "ABC corp", vous placeriez tout votre contenu dans un seul espace de noms abc::.

23
Binary Worrier

ce que je fais en déclarant en avant ressemble à ceci:

 namespace abc { namespace sub { namespace subsub { class MyClass; }}}

Mes déclarations en aval sont réduites en une seule ligne. La lisibilité de la déclaration aval est sacrifiée en contrepartie de la lisibilité du reste du code. Et pour les définitions, je n’utilise pas d’indentation non plus:

 namespace abc {
 namespace sub {
 namespace subsub {

 class MyClass 
 {
    public:
       MyClass();

       void normalIntendationsHere() const;
 };

 }
 }
 }

Utiliser ce style nécessite un peu de discipline au début, mais c'est le meilleur compromis pour moi.

17
doc

Au moins comme une petite aide, dans certains cas, vous pouvez le faire:

namespace foo = A::B::C::D;

Et puis référence A :: B :: C :: D comme foo. Mais seulement dans certains cas.

8
Bill Lynch

Vous pouvez ignorer l'indentation. J'écris souvent

namespace myLib { namespace details {

/* source code */

} } /* myLib::details */

Le code source C++ est finalement compilé en binaire, contrairement à C #/Java qui reste dans le binaire. Par conséquent, l'espace de noms fournit simplement une solution parfaite pour les conflits de noms de variables. Il n'est pas destiné à la hiérarchie de classes.

Je garde souvent un ou deux niveaux d'espace de nom dans le code.

5
cuteCAT

Tout d'abord, vous pouvez éviter l'indentation de l'espace de noms, car il n'y a aucune raison pour cela.

L'utilisation d'espaces de noms dans les exemples n'affichera pas le pouvoir des espaces de noms. Et leur pouvoir quant à moi divise les domaines du Domaine les uns des autres. Divisez les classes utilitaires des classes commerciales.

Il suffit de ne pas mélanger différentes hiérarchies d’espaces de noms dans le même fichier .h. Les espaces de noms sont une sorte de commentaire supplémentaire pour votre interface de déclaration de fonctions. La recherche sur les espaces de noms et les noms de classe devrait expliquer beaucoup de choses.

namespace product
{
namespace DAO
{

class Entity
{
};
4
Mykola Golubyev

J'ai trouvé que vous pouvez en quelque sorte imiter l'espace de noms c # comme ceci;

namespace ABC_Maths{
    class POINT2{};
    class Complex{};
}

namespace ABC_Maths_Conversion{
    ABC_MATHS::Complex ComplexFromPOINT2(ABC_MATHS::POINT2)
    {return new ABC_MATHS::Complex();}

    ABC_MATHS::POINT4 POINT2FromComplex(ABC_MATHS::COMPLEX)
    {return new ABC_MATHS::POINT2();}
}

namespace ABC
{
}

Mais le code ne semble pas être très bien rangé. et je m'attendrais à avoir une longue utilisation

Il est préférable d’intégrer autant de fonctionnalités dans des classes comme

namespace ABC{
    class Maths{
        public:
        class POINT2{};
        class Complex:POINT2{};
        class Conversion{
            public:
            static Maths.Complex ComplexFromPOINT2(MATHS.POINT2 p)
            {return new MATHS.Complex();}

            static MATHS.POINT2 POINT2FromComplex(MATHS.COMPLEX p)
            {return new ABC::MATHS.POINT2();}// Can reference via the namespace if needed
} /*end ABC namespace*/

Et c'est encore un peu long. mais se sent un peu OO.

Et entend comment cela semble mieux fait

namespace ABC
{
    class POINT2{};
    class Complex:POINT2{};
    Complex ComplexFromPOINT2(POINT2 p){return new Complex();}
    POINT2 POINT2FromComplex(Complex){return new POINT2();}
}

entend à quoi ressemblerait les usages

int main()
{
    ABC_Maths::Complex p = ABC_Maths_Conversion::ComplexFromPOINT2(new ABC_MATHS::POINT2());

    // or THE CLASS WAY

    ABC.Maths.Complex p = ABC.Maths.Conversion.ComplexFromPOINT2(new ABC.Maths.POINT2());

    // or if in/using the ABC namespace

    Maths.Complex p = Maths.Conversion.ComplexFromPOINT2(new Maths.POINT2());

    // and in the final case

    ABC::Complex p = ABC::ComplexFromPOINT2(new ABC::POINT2());
}

sa été intéressant de savoir pourquoi je n'ai jamais utilisé les espaces de noms c ++ comme je le ferais avec c #. Il serait trop long et ne fonctionnerait jamais de la même manière que les espaces de noms c #.

la meilleure utilisation des espaces de noms en c ++ est de cesser de dire à ma fonction super cout (qui sonne chaque fois qu’elle s'appelle) de se mélanger à la fonction std :: cout (qui est beaucoup moins impressionnante).

Ce n’est pas parce que c # et c ++ ont des espaces de noms que cela veut dire la même chose. ils sont différents mais similaires. L'idée des espaces de noms c # doit provenir d'espaces de noms c ++. quelqu'un doit avoir vu ce qu'une chose semblable mais différente pourrait faire et ne pas avoir assez de puissance d'imagination pour lui donner son propre nom original, tel que "ClassPath", ce qui aurait plus de sens comme chemin vers les classes plutôt que pour fournir nommer des espaces où chaque espace peut avoir les mêmes noms

J'espère que ça aidera quelqu'un

J'ai oublié de dire que toutes ces méthodes sont valables et que l'utilisation modérée des deux premières peut être incorporée dans la troisième pour créer une bibliothèque qui a un sens, c'est-à-dire (pas un bon exemple).

_INT::POINT2{}

et

_DOUBLE::POINT2{}

afin que vous puissiez changer le niveau de précision en utilisant 

#define PREC _DOUBLE 
// or #define PREC _INT 

puis en créant une instance de PREC :: POINT2 pour POINT2 à double précision

Ce n’est pas une chose facile à faire avec des espaces de noms c # ou Java

évidemment, ce n'est qu'un exemple. Pensez à la lecture de l'usage.

0
Ace_Of_John