C++编程法则100条(10)using用法之声明

Posted 奇妙之二进制

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++编程法则100条(10)using用法之声明相关的知识,希望对你有一定的参考价值。

🥇 关于博主👇🏻👇🏻👇🏻

👀 作者简介: 热衷于知识探索和分享的技术博主。
💂 csdn主页::【奇妙之二进制
✍️ 微信公众号:【Linux 世界

🎉精彩专栏:

   💪 【C++编程法则100条
   🎓 【面向工作git基础教程
​   🧡 【C++11新特性深入剖析
​   📚 【shell脚本编程基础与实战
​   🌎 【Linux网络编程面试
   ✍️ 【C++编译工具cmake入门到精通
   🤩 【Linux文本处理三剑客
   😉 【C++模板编程
   🥰 【VIM实用指南
   🔥 【Linux C/C++编译链接和调试调优
   ✨ 【面向对象分析和设计
   🎉 【Ubuntu/Linux系统管理
   🤔 【C/C++笔面试精选
   ✔️ 【Linux并发编程面试与实战
   🚀 【C/C++常用开源库实战
   😊 【Linux常用命令详解
​ …

💂关于作者: 曾就职于国内知名安防上市公司,现就职于国内知名AMR机器人公司,担任高级系统软件工程师。2020年至今保持CSDN博客专家,CSDN C/C++领域优质创作者头衔。全网5万+粉丝。十载寒冰,难凉热血;多年过去,历经变迁,物是人非。 然而,对于技术的探索和追求从未停歇。 💪坚持创作,热衷分享,初心未改,继往开来!

文章目录

参考:https://en.cppreference.com/w/cpp/language/using_declaration

前言

using用法非常之多,总体分为两类:

  • 将定义在别处的变量、类型或者函数引入到using声明语句所在的作用域
  • 为类型起别名

我们今天主要看声明的用法。

语法

using 声明符列表;

列表以,分隔。

其定义是将定义在别处的变量、类型或者函数引入到using声明语句所在的作用域

这句话隐藏了非常多的信息。这里的别处其实是指其他的命名空间、其他的类内,例如当前处于命名空间a,想使用命名空间std提供的类型定义或者,要么在使用时加上命名空间前缀,如std::string, 要么声明string所在的命名空间,也就是使用using语句:
using std::string
这样,从该using声明语句开始,到using所在的作用域结束这个区间内,我们可以直接使用string,而无需指明其所属的命名空间。

可以看到using是有作用域的,这个作用域包括,作用域、命名空间作用域和类作用域。

使用场景1 引入其他命名空间的定义

#include <iostream>
#include <string>
 
using std::string;
 
int main()

    string str = "Example";
    using std::cout;
    cout << str;


上述例子用了两条using语句,以一是将string类型引入,二是将对象cout引入。
cout只在main函数局部作用域起作用,而string在该文件内起作用。

如若去除using std::cout直接使用cout,编译器将提示未定义标识符cout:

在main函数之外的foo函数里,cout是不可见的,除非他也加上using std::cout,或者你将using std::cout这条语句放在全局,而且需要在foo函数定义之前。

使用场景2 修改父类成员的访问控制权限

类也是具有作用域的,定义于类A内的东西,在引用时,需要加上作用域A。

目前的语法不支持在继承体系外using 类的成员,但可以在子类内using父类的成员。

子类using父类成员的目的可能是想修改父类成员的访问控制权限(这个场景比较少见),例如父类定义为protected,子类可以在public里使用using,相当于修改了父类定义的权限。

但是父类定义为private的东西,子类using也无法僭越。

上面还隐含了一层意思:using受public、protected、private权限访问控制的影响。

 
class A 
  protected:
    void fun()  
;

class B : public A 
  public:
    using A::fun;
;

int main() 
    B b;
    b.fun();

上面这个例子,fun的访问权限被修改了,所以外部可以访问。

使用场景3 继承构造函数

可以在子类内,用using声明父类的构造函数,这样可以不写子类的构造函数(如果子类没有什么成员需要初始化的话),子类会自动生成和父类形参一致的构造函数,且该构造函数会调用父类形参一致的构造函数。

子类using声明之后,会获得父类的全部构造函数。

例如下面的例子中,A有一个int的构造函数,B内using A:A后,相当于获得了一个这样的构造函数:B(int a) A:(a)

#include <iostream>
#include <string>
 
class A 
  public:
    A(int a) :a_(a) 
    
  private:
    int a_;
;

class B : public A 
 public:
    using A::A;
    
;

int main()

    B b(1);

在这个场景下,using语句还是会受权限访问控制修复符影响。

struct B1  B1(int, ...)  ;
struct B2  B2(double)    ;
 
int get();
 
struct D1 : B1

    using B1::B1; // inherits B1(int, ...)
    int x;
    int y = get();
;
 
void test()

    D1 d(2, 3, 4); // OK: B1 is initialized by calling B1(2, 3, 4),
                   // then d.x is default-initialized (no initialization is performed),
                   // then d.y is initialized by calling get()
 
    D1 e;          // Error: D1 has no default constructor

 
struct D2 : B2

    using B2::B2; // inherits B2(double)
    B1 b;
;
 
D2 f(1.0); // error: B1 has no default constructor

如果子类有成员,那么成员将会采用默认构造函数进行初始化,如果成员没有默认构造函数,那么将会报错。

使用场景4 消除类枚举前缀

类枚举在访问时需要加上类前缀,可以使用using解除。

enum class button  up, down ;
 
struct S

    using button::up;
    button b = up; // OK
;
 
using button::down;
constexpr button non_up = down; // OK
 
constexpr auto get_button(bool is_up)

    using button::up, button::down;
    return is_up ? up : down; // OK

 
enum unscoped  val ;
using unscoped::val; // OK, though needless

以上是关于C++编程法则100条(10)using用法之声明的主要内容,如果未能解决你的问题,请参考以下文章

C++编程法则100条friend友元函数

C++编程法则100条关于内嵌类的使用细节

C++编程法则100条(11)关于&&&修饰成员函数的含义

C++编程法则100条空{}初始化讨论

c++编程 多项式的乘法

c++中typenametypedef以及using关键字用法