cpp笔记第5篇-using关键字

751 阅读3分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

本文是我在掘金平台发表于2022年4月份的,从发表最初累计第13篇博客,希望大家关注我,我将会持续在后端和大数据等领域进行书写更多的文章。

摘要

本文的标题是《2204-17-c++-using关键字》,介绍了using关键字的两大核心用法,导入命名空间和起别名。

本文的工作是在介绍引文[1]工作的基础上,就using关键字的用法进行了分类。

C++using关键字

看google某项目源码时,里面使用了很多using关键字。之前对using关键字的概念,一直停留在引入命名空间中。其实,using关键字还些其他的用途。

一、导入命名空间

  • using关键字最常用的,可能就是导入命名空间。
using namespace std;
using std::cout; 
继承中的作用,改变访问权限
class Base
{
    public:
        void func() { cout << "Hello World" << endl;}
}

// private继承会导致 func的可见性为private
// 可使用using,改变访问权限
class Sub : private Base
{
   publicusing Base::func;
}

继承时子类重写父类方法。子类中如果想重写父类函数,比如名为func的函数。并且,假设父类中关于func函数有不同的版本。如果,子类中重写一个函数,就会隐藏父类中所有同名函数。此时,只能通过显示方式调用父类的方法。即使,子类重新父类中的虚函数(覆盖),也会导致该问题。

这其中的原理,即C++查找命名空间的从内到外的顺序,以及说明C++是使用函数名来唯一标记一个函数的,虽然说在编译的时候,会把参数类型等带上,但是显然,查找函数这一步是在函数名重写之前的,它们都属于编译过程。

举例如下:

class Base
{
    public:
        void func() { // some code
        }
        int func(int n) { // some code
        }
}

class Sub : public Base
{
    public:
        // 此处函数定义,会隐藏父类中 int func(int)方法。
        void func() { // some code
        }
        
}

int main()
{
    Sub s;
    s.func();
    s.func(1); // Error!
}

因此,如果不想隐藏父类的同名方法,可以重写所有同名函数。这未免有些麻烦。使用using关键字,即可解决该问题。

class Base
{
    public:
        void func() { // some code
        }
        int func(int n) { // some code
        }
}

class Sub : public Base
{
    public:
        using Base::func;
        void func() { // some code
        }
        
}

int main()
{
    Sub s;
    s.func();
    s.func(1); // Success!
}

在此可以辨析一下 隐藏/重载/覆盖 的区别。

  1. 重载:同名函数,函数的参数类型、参数个数不同,同域下的函数的关系。继承中,一般不考虑。
  2. 隐藏:子类重写了父类的代码,将父类中的内容隐藏。
  3. 覆盖:只在重写父类虚函数时发生。覆盖的概念,一般是和多态关联的。

可以说,C++

二、起别名

using关键字在 c++ 11 里还可以代替 typedef 关键字,下面举个几个例子。包括反面例子.

#include <iostream>
#include <string>
#include <map>

using std::string;
using string2 = std::string; 

namespace zx{
class A{
  // 不可以在一个类级别的命名空间中导入命名空间
  // using std::string;会报错
	
  using string = std::string; // 不能写成 using std::string;
  // using namespace std; 也不能在类里面使用这样的语法
  using map = std::map<string, string>; // map是个模板类,要实例化!,否则编译不通过
  string f1(){
    using std::string; // 合法
    using pii = std::pair<int, int>; // 可以在一个方法里使用起别名的语法
    return "abc";
  }
};
/
}

// main方法不能在任何有名称的命名空间中,否则会执行错误
int main(){
  // 可以在一个方法级别的命名空间中导入,也可以在源代码级别的命名空间中导入
  using std::string;
  using std::cout;
  cout << "a is \n" ;
  string a = "abc\n";
  cout << a;
  return 0;
}

相关工作

林多在他的博客中介绍了C++中using关键字的用法[1]。

参考

[1]林多,C++using关键字,blog.csdn.net/zxc024000/a…