Espaces de noms (C++)Namespaces (C++)

Un espace de noms est une région déclarative qui fournit une portée aux identificateurs (noms de types, fonctions, variables, etc.) à l'intérieur.A namespace is a declarative region that provides a scope to the identifiers (the names of types, functions, variables, etc) inside it. Les espaces de noms sont utilisés pour organiser le code en groupes logiques et pour éviter les conflits de noms qui peuvent se produire en particulier lorsque votre base de code inclut plusieurs bibliothèques.Namespaces are used to organize code into logical groups and to prevent name collisions that can occur especially when your code base includes multiple libraries. Tous les identificateurs de portée espace de noms sont visibles les uns pour les autres sans qualification.All identifiers at namespace scope are visible to one another without qualification. Les identificateurs en dehors de l’espace de noms peuvent accéder aux membres en utilisant le nom qualifié complet pour chaque std::vector<std::string> vec;identificateur, par exemple, ou par une déclaration using pour un identificateurusing std::stringunique (), ou une directive using pour All identificateurs dans l’espace de nomsusing namespace std;().Identifiers outside the namespace can access the members by using the fully qualified name for each identifier, for example std::vector<std::string> vec;, or else by a using Declaration for a single identifier (using std::string), or a using Directive for all the identifiers in the namespace (using namespace std;). Le code dans les fichiers d'en-tête doit toujours utiliser le nom de l'espace de noms qualifié complet.Code in header files should always use the fully qualified namespace name.

L'exemple suivant montre une déclaration d'espace de noms et trois façons pour le code en dehors de l'espace de noms d'accéder à leurs membres.The following example shows a namespace declaration and three ways that code outside the namespace can accesses their members.

namespace ContosoData
{
    class ObjectManager
    {
    public:
        void DoSomething() {}
    };
    void Func(ObjectManager) {}
}

Utiliser le nom qualifié complet :Use the fully qualified name:

ContosoData::ObjectManager mgr;
mgr.DoSomething();
ContosoData::Func(mgr);

Utiliser une déclaration using pour placer un identificateur dans la portée :Use a using declaration to bring one identifier into scope:

using ContosoData::ObjectManager;
ObjectManager mgr;
mgr.DoSomething();

Utiliser une directive using pour placer tous les éléments de l'espace de noms dans la portée :Use a using directive to bring everything in the namespace into scope:

using namespace ContosoData;

ObjectManager mgr;
mgr.DoSomething();
Func(mgr);

directives usingusing directives

La directive using autorise l’utilisation de tous les noms dans un espace de noms sans le nom d’espace de noms comme qualificateur explicite.The using directive allows all the names in a namespace to be used without the namespace-name as an explicit qualifier. Utilisez une directive using dans un fichier d’implémentation (par exemple, *. cpp) si vous utilisez plusieurs identificateurs différents dans un espace de noms; Si vous utilisez uniquement un ou deux identificateurs, envisagez d’utiliser une déclaration using pour placer ces identificateurs uniquement dans la portée et non dans tous les identificateurs de l’espace de noms.Use a using directive in an implementation file (i.e. *.cpp) if you are using several different identifiers in a namespace; if you are just using one or two identifiers, then consider a using declaration to only bring those identifiers into scope and not all the identifiers in the namespace. Si une variable locale a le même nom qu'une variable d'espace de noms, la variable d'espace de noms est masquée.If a local variable has the same name as a namespace variable, the namespace variable is hidden. Le fait qu'une variable d'espace de noms porte le même nom qu'une variable globale est une erreur.It is an error to have a namespace variable with the same name as a global variable.

Notes

Une directive using peut être placée en haut d'un fichier .cpp (au niveau de la portée de fichier) ou à l'intérieur d'une définition de classe ou de fonction.A using directive can be placed at the top of a .cpp file (at file scope), or inside a class or function definition.

En règle générale, évitez de placer des directives using dans les fichiers d'en-tête (*.h), car n'importe quel fichier qui inclut cet en-tête placera tous les éléments de l'espace de noms dans la portée, ce qui peut provoquer des problèmes de masquage de noms et de conflits de noms très difficiles à déboguer.In general, avoid putting using directives in header files (*.h) because any file that includes that header will bring everything in the namespace into scope, which can cause name hiding and name collision problems that are very difficult to debug. Utilisez toujours des noms qualifiés complets dans un fichier d'en-tête.Always use fully qualified names in a header file. Si ces noms sont trop longs, vous pouvez utiliser un alias d'espace de noms pour les raccourcir.If those names get too long, you can use a namespace alias to shorten them. (Voir ci-dessous.)(See below.)

Déclaration d'espaces de noms et de membres d'espaces de nomsDeclaring namespaces and namespace members

En général, vous déclarez un espace de noms dans un fichier d'en-tête.Typically, you declare a namespace in a header file. Si les implémentations de vos fonctions se trouvent dans un fichier distinct, qualifiez les noms des fonctions, comme dans cet exemple.If your function implementations are in a separate file, then qualify the function names, as in this example.

//contosoData.h
#pragma once
namespace ContosoDataServer
{
    void Foo();
    int Bar();
}

Les implémentations de fonctions dans contosodata. cpp doivent utiliser le nom qualifié complet, même si vous placez une directive using en haut du fichier:Function implementations in contosodata.cpp should use the fully qualified name, even if you place a using directive at the top of the file:

#include "contosodata.h"
using namespace ContosoDataServer;

void ContosoDataServer::Foo() // use fully-qualified name here
{
   // no qualification needed for Bar()
   Bar();
}

int ContosoDataServer::Bar(){return 0;}

Un espace de noms peut être déclaré dans plusieurs blocs, dans un seul fichier et dans plusieurs fichiers.A namespace can be declared in multiple blocks in a single file, and in multiple files. Le compilateur joint les parties pendant le prétraitement et l'espace de noms obtenu contient tous les membres déclarés dans toutes les parties.The compiler joins the parts together during preprocessing and the resulting namespace contains all the members declared in all the parts. Un exemple de ceci est l'espace de noms std qui est déclaré dans chacun des fichiers d'en-tête de la bibliothèque standard.An example of this is the std namespace which is declared in each of the header files in the standard library.

Les membres d’un espace de noms nommé peuvent être définis en dehors de l’espace de noms dans lequel ils sont déclarés par une qualification explicite du nom qui est défini.Members of a named namespace can be defined outside the namespace in which they are declared by explicit qualification of the name being defined. Toutefois, la définition doit figurer après le point de déclaration dans un espace de noms qui englobe l'espace de noms de la déclaration.However, the definition must appear after the point of declaration in a namespace that encloses the declaration's namespace. Par exemple :For example:

// defining_namespace_members.cpp
// C2039 expected
namespace V {
    void f();
}

void V::f() { }        // ok
void V::g() { }        // C2039, g() is not yet a member of V

namespace V {
    void g();
}

Cette erreur peut se produire quand les membres de l'espace de noms sont déclarés dans plusieurs fichiers d'en-tête et que vous n'avez pas inclus ces en-têtes dans le bon ordre.This error can occur when namespace members are declared across multiple header files, and you have not included those headers in the correct order.

Espace de noms globalThe global namespace

Si un identificateur n'est pas déclaré dans un espace de noms explicite, il fait partie de l'espace de noms global implicite.If an identifier is not declared in an explicit namespace, it is part of the implicit global namespace. En général, essayez d’éviter d’effectuer des déclarations au niveau de la portée globale lorsque cela est possible, à l’exception de la fonction maindu point d’entrée, qui doit se trouver dans l’espace de noms global.In general, try to avoid making declarations at global scope when possible, except for the entry point main Function, which is required to be in the global namespace. Pour qualifier explicitement un identificateur global, utilisez l'opérateur de résolution de portée sans nom, comme dans ::SomeFunction(x);.To explicitly qualify a global identifier, use the scope resolution operator with no name, as in ::SomeFunction(x);. Vous différenciez ainsi l'identificateur de tout élément portant le même nom dans un autre espace de noms et votre code devient également plus facile à comprendre.This will differentiate the identifier from anything with the same name in any other namespace, and it will also help to make your code easier for others to understand.

Espace de noms stdThe std namespace

Tous C++ les types et les fonctions de bibliothèque standard sont std déclarés dans l’espace de noms stdou les espaces de noms imbriqués dans.All C++ standard library types and functions are declared in the std namespace or namespaces nested inside std.

Espaces de noms imbriquésNested namespaces

Les espaces de noms peuvent être imbriqués.Namespaces may be nested. Un espace de noms imbriqué ordinaire dispose d'un accès non qualifié aux membres de son parent, mais les membres parents n'ont pas d'accès non qualifié à l'espace de noms imbriqué (sauf s'il est déclaré comme inline), comme illustré dans l'exemple suivant :An ordinary nested namespace has unqualified access to its parent’s members, but the parent members do not have unqualified access to the nested namespace (unless it is declared as inline), as shown in the following example:

namespace ContosoDataServer
{
    void Foo();

    namespace Details
    {
        int CountImpl;
        void Ban() { return Foo(); }
    }

    int Bar(){...};
    int Baz(int i) { return Details::CountImpl; }
}

Les espaces de noms imbriqués ordinaires permettent d'encapsuler les détails d'implémentation interne qui ne font pas partie de l'interface publique de l'espace de noms parent.Ordinary nested namespaces can be used to encapsulate internal implementation details that are not part of the public interface of the parent namespace.

Espaces de noms inline (C++11)Inline namespaces (C++ 11)

Contrairement à un espace de noms imbriqué ordinaire, les membres d'un espace de noms inline sont traités en tant que membres de l'espace de noms parent.In contrast to an ordinary nested namespace, members of an inline namespace are treated as members of the parent namespace. Cette caractéristique permet à une recherche dépendante d’un argument sur les fonctions surchargées de fonctionner sur les fonctions qui ont des surcharges dans un parent et un espace de noms inline imbriqué.This characteristic enables argument dependent lookup on overloaded functions to work on functions that have overloads in a parent and a nested inline namespace. Elle vous permet également de déclarer une spécialisation dans un espace de noms parent pour un modèle qui est déclaré dans l'espace de noms inline.It also enables you to declare a specialization in a parent namespace for a template that is declared in the inline namespace. L'exemple suivant montre comment le code externe est lié à l'espace de noms inline par défaut :The following example shows how external code binds to the inline namespace by default:

//Header.h
#include <string>

namespace Test
{
    namespace old_ns
    {
        std::string Func() { return std::string("Hello from old"); }
    }

    inline namespace new_ns
    {
        std::string Func() { return std::string("Hello from new"); }
    }
}

#include "header.h"
#include <string>
#include <iostream>

int main()
{
    using namespace Test;
    using namespace std;

    string s = Func();
    std::cout << s << std::endl; // "Hello from new"
    return 0;
}

L'exemple suivant vous montre comment déclarer une spécialisation dans un parent d'un modèle qui est déclaré dans un espace de noms inline :The following example shows how you can declare a specialization in a parent of a template that is declared in an inline namespace:

namespace Parent
{
    inline namespace new_ns
    {
         template <typename T>
         struct C
         {
             T member;
         };
    }
     template<>
     class C<int> {};
}

Vous pouvez utiliser des espaces de noms inline comme mécanisme de contrôle de version pour gérer les modifications apportées à l'interface publique d'une bibliothèque.You can use inline namespaces as a versioning mechanism to manage changes to the public interface of a library. Par exemple, vous pouvez créer un espace de noms parent unique et encapsuler chaque version de l'interface dans son propre espace de noms imbriqué dans le parent.For example, you can create a single parent namespace, and encapsulate each version of the interface in its own namespace nested inside the parent. L'espace de noms qui contient la version la plus récente ou préférée est qualifié comme étant inline et est par conséquent exposé comme s'il s'agissait d'un membre direct de l'espace de noms parent.The namespace that holds the most recent or preferred version is qualified as inline, and is therefore exposed as if it were a direct member of the parent namespace. Le code client qui appelle Parent::Class se liera automatiquement au nouveau code.Client code that invokes the Parent::Class will automatically bind to the new code. Les clients qui préfèrent utiliser l'ancienne version peuvent toujours y accéder en utilisant le chemin d'accès qualifié complet à l'espace de noms imbriqué qui possède ce code.Clients that prefer to use the older version can still access it by using the fully qualified path to the nested namespace that has that code.

Le mot clé inline doit être appliqué à la première déclaration de l'espace de noms dans une unité de compilation.The inline keyword must be applied to the first declaration of the namespace in a compilation unit.

L'exemple suivant montre deux versions d'une interface, chacune dans un espace de noms imbriqué.The following example shows two versions of an interface, each in a nested namespace. L'espace de noms v_20 a été modifié à partir de l'interface v_10 et est marqué comme inline.The v_20 namespace has some modification from the v_10 interface and is marked as inline. Le code client qui utilise la nouvelle bibliothèque et appelle Contoso::Funcs::Add appelle la version v_20.Client code that uses the new library and calls Contoso::Funcs::Add will invoke the v_20 version. Le code qui tente d'appeler Contoso::Funcs::Divide reçoit désormais une erreur de compilation.Code that attempts to call Contoso::Funcs::Divide will now get a compile time error. S'ils ont vraiment besoin de cette fonction, ils peuvent toujours accéder à la version v_10 en appelant explicitement Contoso::v_10::Funcs::Divide.If they really need that function, they can still access the v_10 version by explicitly calling Contoso::v_10::Funcs::Divide.

namespace Contoso
{
    namespace v_10
    {
        template <typename T>
        class Funcs
        {
        public:
            Funcs(void);
            T Add(T a, T b);
            T Subtract(T a, T b);
            T Multiply(T a, T b);
            T Divide(T a, T b);
        };
    }

    inline namespace v_20
    {
        template <typename T>
        class Funcs
        {
        public:
            Funcs(void);
            T Add(T a, T b);
            T Subtract(T a, T b);
            T Multiply(T a, T b);
            std::vector<double> Log(double);
            T Accumulate(std::vector<T> nums);
      };
    }
}

Alias d’espace de nomsNamespace aliases

Les noms des espaces de noms doivent être uniques, ce qui signifie qu'ils ne doivent pas être trop courts.Namespace names need to be unique, which means that often they should not be too short. Si la longueur d'un nom rend le code difficile à lire ou est fastidieux à taper dans un fichier d'en-tête où les directives using ne peuvent pas être utilisées, vous pouvez créer un alias d'espaces de noms qui sert d'abréviation pour le nom réel.If the length of a name makes code difficult to read, or is tedious to type in a header file where using directives can’t be used, then you can make a namespace alias which serves as an abbreviation for the actual name. Par exemple :For example:

namespace a_very_long_namespace_name { class Foo {}; }
namespace AVLNN = a_very_long_namespace_name;
void Bar(AVLNN::Foo foo){ }

espaces de noms anonymes ou sans nomanonymous or unnamed namespaces

Vous pouvez créer un espace de noms explicite, mais sans lui donner de nom :You can create an explicit namespace but not give it a name:

namespace
{
    int MyFunc(){}
}

C’est ce qu’on appelle un espace de noms sans nom ou anonyme. il est utile lorsque vous souhaitez rendre les déclarations de variables invisibles pour le code dans d’autres fichiers (c’est-à-dire leur donner une liaison interne) sans avoir à créer un espace de noms nommé.This is called an unnamed or anonymous namespace and it is useful when you want to make variable declarations invisible to code in other files (i.e. give them internal linkage) without having to create a named namespace. Tout le code du même fichier peut voir les identificateurs dans un espace de noms sans nom, mais les identificateurs, ainsi que l'espace de noms lui-même, ne sont pas visibles en dehors de ce fichier ou, plus précisément, à l'extérieur de l'unité de traduction.All code in the same file can see the identifiers in an unnamed namespace but the identifiers, along with the namespace itself, are not visible outside that file—or more precisely outside the translation unit.

Voir aussiSee also

Déclarations et définitionsDeclarations and Definitions