前言:

今天在看vector.h的时候,碰到一个using的奇怪用法,才疏学浅之前没有碰到过,整理一下。

来看下source code:

template<class _Ty,class _Alloc = allocator<_Ty>>class vector: public _Vector_alloc<_Vec_base_types<_Ty, _Alloc>>{    // varying size array of values
private:using _Mybase = _Vector_alloc<_Vec_base_types<_Ty, _Alloc>>;using _Alty = typename _Mybase::_Alty;using _Alty_traits = typename _Mybase::_Alty_traits;public:static_assert(!_ENFORCE_MATCHING_ALLOCATORS || is_same<_Ty, typename _Alloc::value_type>::value,_MISMATCHED_ALLOCATOR_MESSAGE("vector<T, Allocator>", "T"));using value_type = _Ty;using allocator_type = _Alloc;using pointer = typename _Mybase::pointer;using const_pointer = typename _Mybase::const_pointer;using reference = _Ty&;using const_reference = const _Ty&;using size_type = typename _Mybase::size_type;using difference_type = typename _Mybase::difference_type;using iterator = typename _Mybase::iterator;using const_iterator = typename _Mybase::const_iterator;using reverse_iterator = _STD reverse_iterator<iterator>;using const_reverse_iterator = _STD reverse_iterator<const_iterator>;

下面来整理using的三种用法。

1、命名空间的使用

一般为了代码的冲突,都会用命名空间。例如,对于Android代码会使用Android作为命名空间。

namespace android;

在code中使用的时候可以用android::加具体的类方法。也可以直接使用using namespace android;

具体的命名空间使用方法不做过多说明。

2、在类中的作用

(1)在子类中引用基类的成员

来看下source code:

class T5Base {
public:T5Base() :value(55) {}virtual ~T5Base() {}void test1() { cout << "T5Base test1..." << endl; }
protected:int value;
};class T5Derived : private T5Base {
public://using T5Base::test1;//using T5Base::value;void test2() { cout << "value is " << value << endl; }
};

基类中成员变量value是protected,在private继承之后,对于外界这个值为private,也就是说T5Derived的对象无法使用这个value。

如果想要通过对象使用,需要在public下通过using T5Base::value来引用,这样T5Derived的对象就可以直接使用。

同样的,对于基类中的成员函数test1(),在private继承后变为private,T5Derived的对象同样无法访问,通过using T5Base::test1 就可以使用了。

注意,using只是引用,不参与形参的指定。

(2)继承中的作用

改变访问权限

class Base
{public:void func() { cout << "Hello World" << endl;}
}// private继承会导致 func的可见性为private
// 可使用using,改变访问权限
class Sub : private Base
{public:using Base::func;
}

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

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!
}

3、别名指定

这点就是最开始看到的source code。在C++11中提出了通过using指定别名。

例如上面source code 中:

using value_type = _Ty

以后使用value_type value; 就代表_Ty value;

这个让我们想起了typedef,using 跟typedef有什么区别呢?哪个更好用些呢?

例如:

typedef std::unique_ptr<std::unordered_map<std::string, std::string>> UPtrMapSS;

而C++11中:

using UPtrMapSS = std::unique_ptr<std::unordered_map<std::string, std::string>>;

或许从这个例子中,我们是看不出来明显的好处的(而于我来说,以一个第三者的角度,这个例子也难以说服我一定要用C++11的using)。
再来看下:

typedef void (*FP) (int, const std::string&);

若不是特别熟悉函数指针与typedef的童鞋,我相信第一眼还是很难指出FP其实是一个别名,代表着的是一个函数指针,而指向的这个函数返回类型是void,接受参数是int, const std::string&。那么,让我们换做C++11的写法:

using FP = void (*) (int, const std::string&);

我想,即使第一次读到这样代码,并且知道C++11 using的童鞋也能很容易知道FP是一个别名,using的写法把别名的名字强制分离到了左边,而把别名指向的放在了右边,比较清晰。

而针对这样的例子,我想我可以再补充一个例子:

typedef std::string (Foo::* fooMemFnPtr) (const std::string&);using fooMemFnPtr = std::string (Foo::*) (const std::string&);

从可读性来看,using也是要好于typedef的。

那么,若是从可读性的理由支持using,力度也是稍微不足的。来看第二个理由,那就是举出了一个typedef做不到,而using可以做到的例子:alias templates, 模板别名。

template <typename T>
using Vec = MyVector<T, MyAlloc<T>>;// usage
Vec<int> vec;

这一切都会非常的自然。

那么,若你使用typedef来做这一切:

template <typename T>
typedef MyVector<T, MyAlloc<T>> Vec;// usage
Vec<int> vec;

当你使用编译器编译的时候,将会得到类似:error: a typedef cannot be a template的错误信息。

那么,为什么typedef不可以呢?在 n1449 中提到过这样的话:"we specifically avoid the term “typedef template” and introduce the new syntax involving the pair “using” and “=” to help avoid confusion: we are not defining any types here, we are introducing a synonym (i.e. alias) for an abstraction of a type-id (i.e. type expression) involving template parameters." 所以,我认为这其实是标准委员会他们的观点与选择,在C++11中,也是完全鼓励用using,而不用typedef的。

具体的可以看下Effective Modern C++

参考:

https://blog.csdn.net/zxc024000/article/details/79438539

https://zhuanlan.zhihu.com/p/21264013

C++11中using 的使用相关推荐

  1. C++11中头文件type_traits介绍

    C++11中的头文件type_traits定义了一系列模板类,在编译期获得某一参数.某一变量.某一个类等等类型信息,主要做静态检查. 此头文件包含三部分: (1).Helper类:帮助创建编译时常量的 ...

  2. C++11中std::async的使用

    C++11中的std::async是个模板函数.std::async异步调用函数,在某个时候以Args作为参数(可变长参数)调用Fn,无需等待Fn执行完成就可返回,返回结果是个std::future对 ...

  3. C++11中std::packaged_task的使用

    C++11中的std::packaged_task是个模板类.std::packaged_task包装任何可调用目标(函数.lambda表达式.bind表达式.函数对象)以便它可以被异步调用.它的返回 ...

  4. C++11中std::shared_future的使用

    C++11中的std::shared_future是个模板类.与std::future类似,std::shared_future提供了一种访问异步操作结果的机制:不同于std::future,std: ...

  5. C++11中std::future的使用

    C++11中的std::future是一个模板类.std::future提供了一种用于访问异步操作结果的机制.std::future所引用的共享状态不能与任何其它异步返回的对象共享(与std::sha ...

  6. C++/C++11中用于定义类型别名的两种方法:typedef和using

    类型别名(type alias)是一个名字,它是某种类型的同义词.使用类型别名有很多好处,它让复杂的类型名字变得简单明了.易于理解和使用,还有助于程序员清楚地知道使用该类型的真实目的.在C++中,任何 ...

  7. C++/C++11中头文件functional的使用

    <functional>是C++标准库中的一个头文件,定义了C++标准中多个用于表示函数对象(function object)的类模板,包括算法操作.比较操作.逻辑操作:以及用于绑定函数对 ...

  8. 概率论中指数分布介绍及C++11中std::exponential_distribution的使用

    指数分布:在深度学习中,我们经常会需要一个在x=0点处取得边界点(sharp point)的分布.为了实现这一目的,我们可以使用指数分布(exponential distribution): p(x; ...

  9. 概率论中高斯分布(正态分布)介绍及C++11中std::normal_distribution的使用

    高斯分布:最常用的分布是正态分布(normal distribution),也称为高斯分布(Gaussian distribution): 正态分布N(x;μ,σ2)呈现经典的"钟形曲线&q ...

  10. 概率论中伯努利分布(bernoulli distribution)介绍及C++11中std::bernoulli_distribution的使用

    Bernoulli分布(Bernoulli distribution):是单个二值随机变量的分布.它由单个参数ø∈[0,1],ø给出了随机变量等于1的概率.它具有如下的一些性质: P(x=1)= ø ...

最新文章

  1. python生成条形码
  2. java生成验证码登录,生成验证码
  3. 计算机电缆zrdjypvp,ZRDJYPVP电缆什么标准
  4. 利用Docker搭建Redis主从复制集群
  5. css grid布局
  6. 如何获得带时间的ping的结果
  7. 华为全面屏鸿蒙,华为5G概念新机:真全面屏+鸿蒙OS 这才是旗舰手机
  8. iOS相同字符串保存地址唯一
  9. c++怎么打印出句子中的各个单词_小学英语单词汇总篇 身体 食品、饮料 蔬菜...
  10. 常用的WebService
  11. 删除分卷php逻辑,Linux LVM(逻辑卷管理)删除详解
  12. 微软软件基地落户广州
  13. 美国公布最易破解密码 专家称中国网民大量使用
  14. 计算机二级access分数分布_计算机二级office题型及分值分布
  15. Unity游戏开发学习路线
  16. Markdown语法手册
  17. oracle10g dblink优化,dblink如果很慢可以用这种方式优化
  18. 文字转语音软件哪个好,这一款值得推荐
  19. FFMpeg 4.1 音频检测
  20. 基于树莓派+STM32+OneNET云平台打造智能家居系统(一)硬件设计篇

热门文章

  1. esp8266一键安装arduino板_STM32 与 Arduino
  2. php 5.5.9安装,php5.5.9+apache2.4.7 编译安装
  3. ubuntu 17 php版本,Ubuntu 17.10 PHP版本下载_Ubuntu 17.10 每日构建版本下载 17.10 官方正式版_当载软件站...
  4. unity描边发光shader_Unity Shader 边缘高亮、描边
  5. java迭代遍历_JAVA集合中的迭代器的遍历
  6. aar打包依赖 android_快速了解:十四、Android打包编译的进阶流程
  7. Prometheus和Grafana监控实践
  8. UWP 手绘视频创作工具技术分享系列
  9. SQLSERVER的递归
  10. BZOJ-2768: [JLOI2010]冠军调查(超级裸的最小割)