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用法之声明的主要内容,如果未能解决你的问题,请参考以下文章