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
Commentaires
https://aka.ms/ContentUserFeedback.
Bientôt disponible : Tout au long de 2024, nous allons supprimer progressivement GitHub Issues comme mécanisme de commentaires pour le contenu et le remplacer par un nouveau système de commentaires. Pour plus d’informations, consultezEnvoyer et afficher des commentaires pour