web-dev-qa-db-fra.com

Importation d'espaces de noms dans un autre espace de noms

J'aime généralement organiser les classes que je transforme en modules en utilisant des espaces de noms, et je ne vais pas plus de 2 espaces de noms en profondeur, mais il est toujours très difficile de tout qualifier.

J'ai pensé à utiliser les directives sing mais je ne veux pas que certains en-têtes polluent les autres en-têtes. Par exemple:

MyHeader1.hpp

namespace MyLibrary {
    namespace MyModule1 {
        class MyClass1 {
            // stuff
        };
    } // namespace MyModule1
} // namespace MyLibrary

MyHeader2.hpp

namespace MyLibrary {
    namespace MyModule2 {
        // I can import stuff
        // using namespace MyLibrary::MyModule1;
        // using MyLibrary::MyModule1::MyClass1;

        class MyClass2 {
        public:
            void DoSomething(MyLibrary::MyModule1::MyClass1 parameter); // I could do this
            void DoSomething(MyClass1 parameter); // or this (easier)
        };
    } // namespace MyModule2
} // namespace MyLibrary

MyHeader3.hpp

#include <MyModule2/MyHeader2.hpp>

namespace MyLibrary {
    namespace MyModule2 {
        // I understand that MyClass3 may use MyClass1 from here (the using directive would be beneficial), but what if it doesn't; it's left hanging in here import-ed
        // I can see MyLibrary::MyModule1::MyClass1 from here!

        class MyClass3 {
            MyClass2 some_var;
        };
    } // namespace MyModule 2
} // namespace MyLibrary

Le "problème" ici est que je peux voir MyClass1 dans MyHeader3.hpp à l'intérieur de MyModule2 namespace si je l'importe dans MyHeader2.hpp. Je peux voir que ce ne serait pas un problème si les directives sing étaient autorisées au niveau de la classe.

La question est, existe-t-il une meilleure façon de le faire, dois-je simplement tout mettre en place et tout qualifier ou dois-je éviter complètement les espaces de noms?

8
John Mark Caguicla

Non, vous ne devez absolument pas abandonner les espaces de noms! Au lieu de cela, vous devriez mieux organiser votre code et peut-être vérifier à nouveau votre architecture.

Tout d'abord, vous ne devez pas utiliser using namespace MyLibrary::MyModule1; ou using MyLibrary::MyModule1::MyClass1; dans un en-tête, pour éviter la pollution de l'espace de noms, car il n'y a aucun moyen de l'annuler (voir cette question et réponses ).

Une autre option consiste à utiliser des typedefs:

namespace MyLibrary {
    namespace MyModule2 {

        class MyClass2 {
        public:

            typedef MyLibrary::MyModule1::MyClass1 FunctionArg;

            void DoSomething(FunctionArg parameter);
        };
    } // namespace MyModule2
} // namespace MyLibrary

Et si vous utilisez c ++ 11 et versions ultérieures, vous pouvez utiliser using d'une autre manière:

namespace MyLibrary {
    namespace MyModule2 {

        class MyClass2 {
        public:

            using  FunctionArg=MyLibrary::MyModule1::MyClass1;
            void DoSomething(FunctionArg parameter);
        };
    } // namespace MyModule2
} // namespace MyLibrary
11
BЈовић