using, deklaracja
Deklaracja using
wprowadza nazwę do regionu deklaratywnego, w którym pojawia się deklaracja using.
Składnia
using [typename] nested-name-specifier unqualified-id ;
using declarator-list ;
Parametry
nested-name-specyfikr Sekwencja przestrzeni nazw, klas lub wyliczenia i operatorów rozpoznawania zakresu (::), zakończony przez operator rozpoznawania zakresu. Operator rozpoznawania pojedynczego zakresu może służyć do wprowadzenia nazwy z globalnej przestrzeni nazw. Słowo kluczowe typename
jest opcjonalne i może służyć do rozpoznawania nazw zależnych w przypadku wprowadzenia do szablonu klasy z klasy bazowej.
unqualified-id Niekwalifikowane wyrażenie-identyfikatora, które może być identyfikatorem, przeciążonym operatorem, operatorem literału zdefiniowanego przez użytkownika lub nazwą funkcji konwersji, nazwą destruktora klasy lub nazwą szablonu i listą argumentów.
deklarator-lista rozdzielona przecinkami lista [typename
] zagnieżdżonych specyfikatorów-name-specyfikatorów bez kwalifikacji identyfikatorów , a następnie opcjonalnie przez wielokropek.
Uwagi
Deklaracja using wprowadza niekwalifikowaną nazwę jako synonim dla jednostki zadeklarowanej gdzie indziej. Umożliwia ona używanie pojedynczej nazwy z określonej przestrzeni nazw bez wyraźnej kwalifikacji w regionie deklaracji, w którym się pojawia. Jest to w przeciwieństwie do dyrektywy using, która umożliwia używanie wszystkich nazw w przestrzeni nazw bez kwalifikacji. Słowo using
kluczowe jest również używane dla aliasów typów.
Przykład: using
deklaracja w polu klasy
Deklarację using można użyć w definicji klasy.
// 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()
Przykład: using
deklaracja deklarowania elementu członkowskiego
W przypadku użycia do deklarowania elementu członkowskiego deklaracja using musi odwoływać się do składowej klasy bazowej.
// 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()
Przykład: using
deklaracja z jawną kwalifikacją
Członkowie zadeklarowani przy użyciu deklaracji using mogą odwoływać się przy użyciu jawnej kwalifikacji. Prefiks ::
odnosi się do globalnej przestrzeni nazw.
// 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
Przykład: using
synonimy deklaracji i aliasy
W przypadku deklaracji using synonim utworzony przez deklarację odnosi się tylko do definicji prawidłowych w punkcie deklaracji using. Definicje dodane do przestrzeni nazw po deklaracji using nie są prawidłowymi synonimami.
Nazwa zdefiniowana przez deklarację using
jest aliasem oryginalnej nazwy. Nie ma to wpływu na typ, powiązanie ani inne atrybuty oryginalnej deklaracji.
// 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);
}
Przykład: deklaracje lokalne i using
deklaracje
W odniesieniu do funkcji w przestrzeniach nazw, jeśli zestaw deklaracji lokalnych i używanie deklaracji dla pojedynczej nazwy są podane w regionie deklaratywnym, wszystkie muszą odwoływać się do tej samej jednostki lub wszystkie muszą odwoływać się do funkcji.
// 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
}
W powyższym using B::i
przykładzie instrukcja powoduje zadeklarowanie sekundy int i
w g()
funkcji . Instrukcja using B::f
nie powoduje konfliktu z funkcją f(char)
, ponieważ nazwy funkcji wprowadzone przez B::f
program mają różne typy parametrów.
Przykład: Lokalne deklaracje funkcji i using
deklaracje
Deklaracja funkcji lokalnej nie może mieć takiej samej nazwy i typu, jak funkcja wprowadzona przy użyciu deklaracji. Na przykład:
// 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)
}
Przykład: using
deklaracja i dziedziczenie
W odniesieniu do dziedziczenia, gdy deklaracja using wprowadza nazwę z klasy bazowej do zakresu klasy pochodnej, funkcje składowe w klasie pochodnej przesłaniają funkcje wirtualnych składowych o tej samej nazwie i typach argumentów w klasie bazowej.
// 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)
Przykład: using
ułatwienia dostępu deklaracji
Wszystkie wystąpienia nazwy wymienionej w deklaracji using muszą być dostępne. W szczególności jeśli klasa pochodna używa deklaracji using w celu uzyskania dostępu do składowej klasy bazowej, nazwa składowa musi być dostępna. Jeśli nazwa jest nazwą przeciążonej funkcji składowej, wszystkie funkcje o nazwie muszą być dostępne.
Aby uzyskać więcej informacji na temat ułatwień dostępu członków, zobacz Kontrola dostępu do składowych.
// 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
};