déclaration using

La using déclaration introduit un nom dans la région déclarative dans laquelle la déclaration using s’affiche.

Syntaxe

using [typename] nested-name-specifier unqualified-id ;
using declarator-list ;

Paramètres

spécificateur de nom imbriqué Une séquence d’espaces de noms, de classes ou d’énumération et d’opérateurs de résolution d’étendue ( ::), arrêtée par un opérateur de résolution d’étendue. Un opérateur de résolution d’étendue unique peut être utilisé pour introduire un nom à partir de l’espace de noms global. Le mot clé typename est facultatif et peut être utilisé pour résoudre les noms dépendants lorsqu’ils sont introduits dans un modèle de classe à partir d’une classe de base.

unqualified-id : id-expression non qualifié, qui peut être un identificateur, un nom d’opérateur surchargé, un opérateur littéral défini par l’utilisateur ou un nom de fonction de conversion, un nom de destructeur de classe ou un nom de modèle et une liste d’arguments.

declarator-list Une liste séparée par des virgules [typename] nested-name-specifierunqualified-id déclarators, suivie éventuellement d’un ellipsis.

Notes

Une déclaration using introduit un nom non qualifié comme synonyme d’une entité déclarée ailleurs. Il permet à un seul nom d’un espace de noms spécifique d’être utilisé sans qualification explicite dans la région de déclaration dans laquelle il apparaît. Contrairement à la directive using, qui permet à tous les noms d’un espace de noms d’être utilisés sans qualification. La using mot clé est également utilisée pour les alias de type.

Exemple : using déclaration dans le champ de classe

Une déclaration using peut être utilisée dans une définition de classe.

// using_declaration1.cpp
#include <stdio.h>
class B {
public:
   void f(char) {
      printf_s("In B::f()\n");
   }

   void g(char) {
      printf_s("In B::g()\n");
   }
};

class D : B {
public:
   using B::f;    // B::f(char) is now visible as D::f(char)
   using B::g;    // B::g(char) is now visible as D::g(char)
   void f(int) {
      printf_s("In D::f()\n");
      f('c');     // Invokes B::f(char) instead of recursing
   }

   void g(int) {
      printf_s("In D::g()\n");
      g('c');     // Invokes B::g(char) instead of recursing
   }
};

int main() {
   D myD;
   myD.f(1);
   myD.g('a');
}
In D::f()
In B::f()
In B::g()

Exemple : using déclaration pour déclarer un membre

Lorsqu’elle est utilisée pour déclarer un membre, une déclaration using doit faire référence à un membre d’une classe de base.

// using_declaration2.cpp
#include <stdio.h>

class B {
public:
   void f(char) {
      printf_s("In B::f()\n");
   }

   void g(char) {
      printf_s("In B::g()\n");
   }
};

class C {
public:
   int g();
};

class D2 : public B {
public:
   using B::f;   // ok: B is a base of D2
   // using C::g;   // error: C isn't a base of D2
};

int main() {
   D2 MyD2;
   MyD2.f('a');
}
In B::f()

Exemple : using déclaration avec qualification explicite

Les membres déclarés à l’aide d’une déclaration using peuvent être référencés à l’aide d’une qualification explicite. Le :: préfixe fait référence à l’espace de noms global.

// using_declaration3.cpp
#include <stdio.h>

void f() {
   printf_s("In f\n");
}

namespace A {
   void g() {
      printf_s("In A::g\n");
   }
}

namespace X {
   using ::f;   // global f is also visible as X::f
   using A::g;   // A's g is now visible as X::g
}

void h() {
   printf_s("In h\n");
   X::f();   // calls ::f
   X::g();   // calls A::g
}

int main() {
   h();
}
In h
In f
In A::g

Exemple : using synonymes et alias de déclaration

Lorsqu’une déclaration d’utilisation est effectuée, le synonyme créé par la déclaration fait référence uniquement aux définitions valides au moment de la déclaration using. Les définitions ajoutées à un espace de noms après la déclaration using ne sont pas des synonymes valides.

Un nom défini par une using déclaration est un alias pour son nom d’origine. Elle n’affecte pas le type, la liaison ou d’autres attributs de la déclaration d’origine.

// post_declaration_namespace_additions.cpp
// compile with: /c
namespace A {
   void f(int) {}
}

using A::f;   // f is a synonym for A::f(int) only

namespace A {
   void f(char) {}
}

void f() {
   f('a');   // refers to A::f(int), even though A::f(char) exists
}

void b() {
   using A::f;   // refers to A::f(int) AND A::f(char)
   f('a');   // calls A::f(char);
}

Exemple : déclarations et using déclarations locales

En ce qui concerne les fonctions dans les espaces de noms, si un ensemble de déclarations locales et l’utilisation de déclarations pour un nom unique sont données dans une région déclarative, ils doivent tous faire référence à la même entité, ou tous doivent faire référence à des fonctions.

// functions_in_namespaces1.cpp
// C2874 expected
namespace B {
    int i;
    void f(int);
    void f(double);
}

void g() {
    int i;
    using B::i;   // error: i declared twice
    void f(char);
    using B::f;   // ok: each f is a function
}

Dans l’exemple ci-dessus, l’instruction using B::i entraîne la déclaration d’une seconde int i dans la g() fonction. L’instruction using B::f n’est pas en conflit avec la f(char) fonction, car les noms de fonction introduits par B::f différents types de paramètres.

Exemple : déclarations et using déclarations de fonction locale

Une déclaration de fonction locale ne peut pas avoir le même nom et le même type qu’une fonction introduite à l’aide de la déclaration. Par exemple :

// functions_in_namespaces2.cpp
// C2668 expected
namespace B {
    void f(int);
    void f(double);
}

namespace C {
    void f(int);
    void f(double);
    void f(char);
}

void h() {
    using B::f;          // introduces B::f(int) and B::f(double)
    using C::f;          // C::f(int), C::f(double), and C::f(char)
    f('h');              // calls C::f(char)
    f(1);                // C2668 ambiguous: B::f(int) or C::f(int)?
    void f(int);         // C2883 conflicts with B::f(int) and C::f(int)
}

Exemple : using déclaration et héritage

En ce qui concerne l’héritage, lorsqu’une déclaration using introduit un nom d’une classe de base dans une étendue de classe dérivée, les fonctions membres de la classe dérivée remplacent les fonctions membres virtuelles avec le même nom et les mêmes types d’arguments dans la classe de base.

// using_declaration_inheritance1.cpp
#include <stdio.h>
struct B {
   virtual void f(int) {
      printf_s("In B::f(int)\n");
   }

   virtual void f(char) {
      printf_s("In B::f(char)\n");
   }

   void g(int) {
      printf_s("In B::g\n");
   }

   void h(int);
};

struct D : B {
   using B::f;
   void f(int) {   // ok: D::f(int) overrides B::f(int)
      printf_s("In D::f(int)\n");
   }

   using B::g;
   void g(char) {   // ok: there is no B::g(char)
      printf_s("In D::g(char)\n");
   }

   using B::h;
   void h(int) {}   // Note: D::h(int) hides non-virtual B::h(int)
};

void f(D* pd) {
   pd->f(1);     // calls D::f(int)
   pd->f('a');   // calls B::f(char)
   pd->g(1);     // calls B::g(int)
   pd->g('a');   // calls D::g(char)
}

int main() {
   D * myd = new D();
   f(myd);
}
In D::f(int)
In B::f(char)
In B::g
In D::g(char)

Exemple : using accessibilité de la déclaration

Toutes les instances d’un nom mentionné dans une déclaration using doivent être accessibles. En particulier, si une classe dérivée utilise une déclaration using pour accéder à un membre d’une classe de base, le nom du membre doit être accessible. Si le nom est celui d’une fonction membre surchargée, toutes les fonctions nommées doivent être accessibles.

Pour plus d’informations sur l’accessibilité des membres, consultez Contrôle d’accès aux membres.

// using_declaration_inheritance2.cpp
// C2876 expected
class A {
private:
   void f(char);
public:
   void f(int);
protected:
   void g();
};

class B : public A {
   using A::f;   // C2876: A::f(char) is inaccessible
public:
   using A::g;   // B::g is a public synonym for A::g
};

Voir aussi

Espaces de noms
Mots clés