宣言を使用する
using の宣言は using の宣言が宣言領域に表示される名前です。
using [typename][::] nested-name-specifier unqualified-id
using :: unqualified-id
解説
名前は他の場所で宣言されているエンティティのシノニムです。これは特定の名前空間から 個々 の名前が 明示的な修飾 なしで使用できるようになります。これは名前空間の名前を修飾子なしで使用できる 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;
using B::g;
void f(int) {
printf_s("In D::f()\n");
f('c');
}
void g(int) {
printf_s("In D::g()\n");
g('c');
}
};
int main() {
D myD;
myD.f(1);
myD.g('a');
}
使用した場合はメンバー宣言を基本クラスのメンバーを宣言するときに指定する必要があります。
// 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');
}
宣言と宣言されたメンバーは明示的な修飾を使用して参照できます。:: のプレフィックスがグローバル名前空間について説明します。
// 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
using A::g; // A's g
}
void h() {
printf_s("In h\n");
X::f(); // calls ::f
X::g(); // calls A::g
}
int main() {
h();
}
宣言を使用するとに設定すると宣言によって作成されるシノニムが使用する宣言時に有効であるシグネチャのみを参照します。使用する宣言の後の名前空間に追加される定義に無効なシノニムです。
宣言を使用してによって定義された名前は元の名前のエイリアスです。コントロールは元の宣言の種類リンクまたは他の属性には影響しません。
// 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);
}
名前空間の関数に対して一連のローカル宣言と一つの名前に使用する宣言が宣言領域で指定した場合すべて同じエントリを参照する必要があります。またすべて関数を参照する必要があります。
// 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 で導入された関数名に異なるパラメーターの型を持つため競合しません。
ローカル関数の宣言は宣言で導入された関数と同じ名前および型を含むことはできません。次に例を示します。
// 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_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);
}
宣言を使用するには名前のすべてのインスタンスがアクセスできる必要があります。特に基本クラスのメンバーにアクセスする場合は派生クラスで宣言を使用する場合はメンバー名がアクセスできる必要があります。名前がオーバーロードされたメンバー関数の場合関数名すべてのアクセス可能である必要があります。
メンバーのアクセシビリティの詳細については アクセスコントロール は" " を参照してください。
// 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
};