C++ 中的 using 用法有很多种,我们下面剖析下常见几种场景:
- using 关键字给类型增加别名
- using 用于继承中的同名函数
- using 关键字用于构造函数
1. using 关键字给类型增加别名
typedef int my_int1; using my_int2 = int; void test04() { my_int1 a = 100; my_int2 b = 200; }
对于普通类型 using 和 typedef 用法很类似,using 主要能力在于模板泛型中定义类型别名,如下代码所示:
//typedef std::vector<int> my_type; // 如果定义带有模板参数的类型, typedef 无能为力 //template<class T> typedef std::vector<T> my_type; // 报错 template<class T> using my_type = std::vector<T> ; // 正确
所以, using 更加能够适应 C++ 泛型编程的场景。
2. using 用于继承中的同名函数
当子类和父类的函数重名之后,会自动隐藏父类的同名函数。此时,如果要用父类的函数,就必须增加父类类作用域来访问。使用 using 可以避免隐藏父类的同名函数。
#include <iostream> using namespace std; class Base1 { public: void show(int) { cout << "Base1::show(int)" << endl; } void show(int, int) {} }; class Derived1 : Base1 { public: // 父类的函数禁止在子类中隐藏 using Base1::show; void show() {} // 使用 using 禁止隐藏父类同名函数 // 假设子类和父类的函数的版本一样(参数个数、参数类型、函数名),此时还是会隐藏父类函数。 void show(int) { cout << "Derived1::show(int)" << endl; } }; void test05() { Derived1 d; // d.show(); d.show(10); // d.show(10, 20); }
3. using 关键字用于构造函数
using 可以继承父类的构造函数,对于子类的成员可以使用就地初始化。
注意:父类的构造函数,如果没有默认的话,不会自动继承。
class Base2 { public: Base2(int a) { m_a = a; m_b = 0; } Base2(int a = 100, int b= 200) { cout << "Base2::Base2(int, int)" << endl; m_a = a; m_b = b; } public: int m_a; int m_b; }; class Derived2 : Base2 { public: using Base2::Base2; /* Derived2(int a, int b) : Base2(a, b) { cout << "Derived2::Derived2(int, int)" << endl; } */ /* Derived2(int a) : Base2(a) {} Derived2(int a, int b) : Base2(a, b) {} */ public: int m_c{}; int m_d{}; }; void test06() { // 1. 由于C++编译期要求:如果父类没有默认构造, // 需要初始化列表指定构造函数。所以,子类必须增加构造函数。 // 2. 假设:能够把父类的构造函数继承下来,这样的话, // 子类就不需要额外去写一些没有意义的构造函数。 // Derived2 d1(10); Derived2 d2(10, 20); }