using 선언은 using 선언이 나타나는 선언 영역에 이름을 도입합니다.
구문
using [typename] nested-name-specifier unqualified-id ;
using declarator-list ;
매개 변수
nested-name-specifier 범위 확인 연산자로 끝나는 일련의 네임스페이스, 클래스 또는 열거형 이름과 범위 확인 연산자(::)입니다. 단일 범위 확인 연산자를 사용하여 전역 이름 공간에서 이름을 도입할 수 있습니다.
typename 키워드는 선택 사항이며 기본 클래스에서 클래스 템플릿에 도입될 때 종속 이름을 확인하는 데 사용될 수 있습니다.
unqualified-id 식별자, 오버로드된 연산자 이름, 사용자 정의 리터럴 연산자 또는 변환 함수 이름, 클래스 소멸자 이름 또는 템플릿 이름 및 인수 목록일 수 있는 정규화되지 않은 ID 식입니다.
declarator-list [typename] nested-name-specifierunqualified-id 선언자의 쉼표로 구분된 목록이며 선택적으로 줄임표가 뒤에옵니다.
설명
using 선언은 다른 곳에서 선언된 엔터티에 대한 동의어로 정규화되지 않은 이름을 도입합니다. 이는 특정 네임스페이스의 단일 이름이 나타나는 선언 영역에서 명시적인 한정 없이 사용될 수 있도록 허용합니다. 이는 네임스페이스의 모든 이름을 한정 없이 사용할 수 있도록 허용하는 using 지시문과 대조됩니다.
using 키워드는 형식 별칭에도 사용됩니다.
예: 클래스 필드의 using 선언
클래스 정의에서 using 선언을 사용할 수 있습니다.
// 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()
예: 멤버 선언을 위한 using 선언
멤버를 선언하는 데 사용되는 경우 using 선언은 기본 클래스의 멤버를 참조해야 합니다.
// 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()
예: 명시적 한정이 있는 using 선언
using 선언을 사용하여 선언된 멤버는 명시적 한정자를 사용하여 참조할 수 있습니다.
:: 접두사는 전역 네임스페이스를 나타냅니다.
// 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
예: using 선언 동의어 및 별칭
using 선언이 만들어지면 선언에서 만든 동의어는 using 선언의 지점에서 유효한 정의만 참조합니다. using 선언 뒤에 네임스페이스에 추가된 정의는 유효한 동의어가 아닙니다.
using 선언으로 정의된 이름은 원래 이름의 별칭입니다. 원래 선언의 형식, 연결 또는 기타 특성에는 영향을 주지 않습니다.
// 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);
}
예: 로컬 선언 및 using 선언
네임스페이스의 함수와 관련하여 단일 이름에 대한 로컬 선언 집합과 using 선언이 선언 영역에 제공되는 경우 모두 동일한 엔터티를 참조하거나 모두 함수를 참조해야 합니다.
// 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
}
위의 예에서 using B::i 문은 두 번째 int i가 g() 함수에서 선언되도록 합니다.
using B::f 문은 f(char)에 의해 도입된 함수 이름이 다른 매개 변수 형식을 가지므로 B::f 함수와 충돌하지 않습니다.
예: 로컬 함수 선언 및 using 선언
로컬 함수 선언은 using 선언으로 도입된 함수와 동일한 이름 및 형식을 가질 수 없습니다. 예시:
// 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)
}
예: using 선언 및 상속
상속과 관련하여 using 선언이 기본 클래스의 이름을 파생 클래스 범위에 도입하는 경우 파생 클래스의 멤버 함수는 기본 클래스의 동일한 이름 및 인수 형식을 사용하여 가상 멤버 함수를 재정의합니다.
// 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)
예: using 선언 접근성
using 선언에 언급된 이름의 모든 인스턴스에 액세스할 수 있어야 합니다. 특히 파생 클래스가 using 선언을 사용하여 기본 클래스의 멤버에 액세스하는 경우 멤버 이름에 액세스할 수 있어야 합니다. 이름이 오버로드된 멤버 함수의 이름인 경우 명명된 모든 함수에 액세스할 수 있어야 합니다.
멤버 접근성에 대한 자세한 내용은 멤버 액세스 제어를 참조하세요.
// 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
};