using 声明
先来看 using 声明在类中的应用:
代码1
#include <iostream>
using namespace std;
struct A {
void f(int) {cout << "A::f(int)" << endl;}
};
struct S : A {
};
int main()
{
S s;
s.f(1); // A::f(int)
}
- 类 S 继承了类 A 的成员函数 f,所以类 S 的实例 s 调用 f 输出为 A::f
代码2
#include <iostream>
using namespace std;
struct A {
void f(int) {cout << "A::f(int)" << endl;}
};
struct S : A {
void f(double) {cout << "S::f(double)" << endl;}
};
int main()
{
S s;
s.f(1); // S::f(double)
}
- 类 S 继承了类 A 的成员函数 f,同时类 S 也定义了成员函数 f
- 类 S 的成员函数 f 遮蔽了基类中的同名函数 f,所以 S 的实例 s 调用 f 输出为 S::f
代码3
#include <iostream>
using namespace std;
struct A {
void f(int) {cout << "A::f(int)" << endl;}
};
struct S : A {
using A::f;
void f(double) {cout << "S::f(double)" << endl;}
};
int main()
{
S s;
s.f(1); // A::f(int)
}
- 类 S 继承了类 A 的成员函数 f,同时类 S 也定义了成员函数 f
- 类 S 通过 using 声明将基类 A 的成员函数 f 引入自己的作用域。类 S 的成员函数 f 与基类 A 的同名函数形成重载关系。
- 参数为整型,所以 S 的实例 s 调用 f 输出为 A::f
代码4
#include <iostream>
using namespace std;
struct A {
void f(int) {cout << "A::f(int)" << endl;}
};
struct B {
void f(double) {cout << "S::f(double)" << endl;}
};
struct S : A, B {
};
int main()
{
S s;
s.f(1); // compile error
}
- 类 S 同时继承了类 A 和类 B 的成员函数 f,两者形成竞争关系。
- 编译器不能判断 S 的实例 s 所调用的成员函数 f 来自类 A 还是类 B,故编译出错。
代码5
#include <iostream>
using namespace std;
struct A {
void f(int) {cout << "A::f(int)" << endl;}
};
struct B {
void f(double) {cout << "S::f(double)" << endl;}
};
struct S : A, B {
using A::f;
using B::f;
};
int main()
{
S s;
s.f(1); // A::f(int)
}
- 类 S 同时继承了类 A 和类 B 的成员函数 f。
- 类 S 通过 using 声明将基类 A 和基类 B 的成员函数 f 都引入自己的作用域。基类 A 和基类 B 的同名函数在类 S 中形成重载关系。
- 参数为整型,所以 S 的实例 s 调用 f 输出为 A::f
C++17的 using 声明
在 C++17 中多个 using 声明可以通过逗号连接起来。
代码6
#include <iostream>
using namespace std;
struct A {
void f(int) {cout << "A::f(int)" << endl;}
};
struct B {
void f(double) {cout << "S::f(double)" << endl;}
};
struct S : A, B {
using A::f, B::f; // C++17
};
int main()
{
S s;
s.f(1); // A::f(int)
}
C++17的变长 using 声明
通过使用加了 ... 的 using 声明,可以将变长模板参数类型中的using 声明转化为多个用逗号合成的变长 using 声明。
#include <iostream>
#include <string>
using namespace std;
template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; };
template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>;
int main()
{
overloaded s{
[](int){cout << "int" << endl;},
[](double){cout << "double" << endl;},
[](string){cout << "string" << endl;},
};
s(1); // int
s(1.); // double
s("1"); // string
}