using 关键字在 C++ 中的几种用法
目录
对C++中 using关键字的几种用法的总结:
1. using 声明
using 声明 (using declaration)
是将命名空间中单个名字注入到当前作用域的机制,使得在当前作用域下访问另一个作用域下的成员时无需使用限定符 ::
1 2 3 4 5 6 |
// ... { using std::map map<int, std::string> the_map; //ok } map<int, std::string> the_map2; //error |
using 声明将其它 namespace 的成员引入本命名空间的 当前作用域 (包括其嵌套作用域) 。一个 using 声明一次只引入一个命名空间成员,它使得无论程序中使用哪些名字,都非常准确。
利用 using 声明,可以改变派生类对父类成员的访问控制:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
class Base{ protected: int bn1; int bn2; }; class Derived: private Base{ public: using Base::bn1; }; class DerivedAgain: public Derived{ }; int main(){ Derived d; DerivedAgain da; d.bn1 = 1; d.bn2 = 2; //error, 'bn2' is a private member of 'Base' da.bn1 = 3; //ok std::cout<<d.bn1<<std::endl; return 0; } |
尽管 Derived 对 base 是私有继承,但通过 using 声明,我们还是可以在 Derived 中访问其成员,且后续的继承同样不受 private 限定的影响。
2. using 指示 (引入命名空间)
using 指示 (using directive)
是使一个命名空间中的 所有 名字都在该作用域中可见的机制。这是最常用的方式了。需要注意的是命名冲突问题。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
#include <iostream> namespace n1{ int n1_member = 10; int m = 11; } int m = 12; int main(){ using namespace n1; std::cout<<n1_member<<std::endl; //std::cout<<m<<std::endl; //error 命名冲突 std::cout<<::m<<std::endl; int m = 13; //ok, 局部变量屏蔽命名空间变量 std::cout<<m<<std::endl; return 0; } |
Notice: 尽管 using指示很方便,但在实际工作中应该尽量避免:它一下子将另一个 namespace 中的成员全部引入了,一不小心就会出现命名空间污染问题。
3. 类型重定义,取代 typedef
1 |
using alias = typename |
这是 C++11 中的新用法,比 typedef 更能表达别名的定义。
1 2 3 4 5 6 7 8 |
using fun = void (*)(int, int); //typedef void (*fun)(int, int); //与上一句等价 using int16 = short; //typedef short int16; //与上一句等价 int main(){ std::cout<<sizeof(int16)<<std::endl; } |
在 C++98/03 中 ,typedef 重定义有一些限制,比如,模板。
我们想实现这样一个模板:将一个 int 映射到任意类型,类似于我们想表达这种效果:
1 2 3 4 |
typedef std::map<int, int> map_int_t; typedef std::map<int, std::string> map_str_t; typedef std::map<int, bool> map_b_t; //... Others |
我们在 C++98/03 中必须这样写:
1 2 3 4 5 6 7 8 9 10 |
template<typename Val> struct int_map{ typedef std::map<int, Val> type; }; int main(){ int_map<int>::type imap; return 0; } |
在C++11 中,我们可以使用 using 重定义模板
1 2 3 4 5 6 7 8 |
template<typename Val> using int_map_t = std::map<int, Val>; int main(){ int_map_t<int> imap; return 0; } |
写的不错,点个赞