using那些事

基本使用

局部与全局using,具体操作与使用见下面案例:

  1. #include <iostream>
  2. #define isNs1 1
  3. //#define isGlobal 2
  4. using namespace std;
  5. void func()
  6. {
  7. cout<<"::func"<<endl;
  8. }
  9. namespace ns1 {
  10. void func()
  11. {
  12. cout<<"ns1::func"<<endl;
  13. }
  14. }
  15. namespace ns2 {
  16. #ifdef isNs1
  17. using ns1::func; /// ns1中的函数
  18. #elif isGlobal
  19. using ::func; /// 全局中的函数
  20. #else
  21. void func()
  22. {
  23. cout<<"other::func"<<endl;
  24. }
  25. #endif
  26. }
  27. int main()
  28. {
  29. /**
  30. * 这就是为什么在c++中使用了cmath而不是math.h头文件
  31. */
  32. ns2::func(); // 会根据当前环境定义宏的不同来调用不同命名空间下的func()函数
  33. return 0;
  34. }

完整代码见:using_global.cpp

改变访问性

  1. class Base{
  2. public:
  3. std::size_t size() const { return n; }
  4. protected:
  5. std::size_t n;
  6. };
  7. class Derived : private Base {
  8. public:
  9. using Base::size;
  10. protected:
  11. using Base::n;
  12. };

类Derived私有继承了Base,对于它来说成员变量n和成员函数size都是私有的,如果使用了using语句,可以改变他们的可访问性,如上述例子中,size可以按public的权限访问,n可以按protected的权限访问。完整代码见:derived_base.cpp

函数重载

在继承过程中,派生类可以覆盖重载函数的0个或多个实例,一旦定义了一个重载版本,那么其他的重载版本都会变为不可见。

如果对于基类的重载函数,我们需要在派生类中修改一个,又要让其他的保持可见,必须要重载所有版本,这样十分的繁琐。

  1. #include <iostream>
  2. using namespace std;
  3. class Base{
  4. public:
  5. void f(){ cout<<"f()"<<endl;
  6. }
  7. void f(int n){
  8. cout<<"Base::f(int)"<<endl;
  9. }
  10. };
  11. class Derived : private Base {
  12. public:
  13. using Base::f;
  14. void f(int n){
  15. cout<<"Derived::f(int)"<<endl;
  16. }
  17. };
  18. int main()
  19. {
  20. Base b;
  21. Derived d;
  22. d.f();
  23. d.f(1);
  24. return 0;
  25. }

如上代码中,在派生类中使用using声明语句指定一个名字而不指定形参列表,所以一条基类成员函数的using声明语句就可以把该函数的所有重载实例添加到派生类的作用域中。此时,派生类只需要定义其特有的函数就行了,而无需为继承而来的其他函数重新定义。

完整代码见:using_derived.cpp

取代typedef

C中常用typedef A B这样的语法,将B定义为A类型,也就是给A类型一个别名B

对应typedef A B,使用using B=A可以进行同样的操作。

  1. typedef vector<int> V1;
  2. using V2 = vector<int>;

完整代码见:using_typedef.cpp