语法:
using alias = typename; //使用别名去替代原始类型(重命名)
在C++11中,我们可以使用这样的语法来替代typedef的功能
using ULL = unsigned long long; //typedef unsigned long long ULL;
using func = void(*)(int, int); //typedef void(*func)(int, int);
在Effective Modern C++中的条款9说明了, 使用using替代typedef。
当我们想实现一个这样的模板: 将一个int映射到任意类型的模板。类似于下面的功能:
typedef std::map<int, int> mapIntInt;
typedef std::map<int, bool> mapIntBool;
typedef std::map<int, std::string> mapIntString;
//...
在C++98/03中,我们必须这样写才能实现:
template <class Val>
struct mapInt{
typedef std::map<int, Val> type;
};
int main(){
mapInt<int>::type imap; //将int映射到int的
mapInt<bool>::type bmap; //将int映射到bool的
mapInt<std::string>::type smap; //将int映射到string的
return 0;
}
在C++11中,我们可以直接使用using重定义模板。
template <class Val>
using mapInt = std::map<int, Val>;
int main(){
mapInt<int> imap;
mapInt<bool> bmap;
mapInt<std::string> smap;
return 0;
}
using这个作用也比较常见,比如在vector.h中就有:
template<class _Ty,class _Alloc = allocator<_Ty>>class vector: public _Vector_alloc<_Vec_base_types<_Ty, _Alloc>>
{
public:
using value_type = _Ty;
using allocator_type = _Alloc;
}
using声明是将命名空间中某个名字单独引入到当前作用域。这使得我们在当前作用域下可以直接使用该名字而无需使用作用域限定符::。
using std::string;//此时string类的作用域前不需要添加std::
string s = "123";
注意对比以下两种写法:如果基类ClassType是个模板,就需要加typename
using typename ClassType::ModuleType;
using ClassType::ModuleType;
using声明可以改变派生类对父类成员的访问权限。
class Base{
protected:
int bn1;
int bn2;
};
class Derived: private Base{ //私有继承
public:
using Base::bn1; //在当前作用域中引入了父类的保护成员, 在当前作用域中可以访问
};
class DerivedAgain: public Derived{ //在Derived的子类中仍然可以访问bn1
};
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类以及其后续派生类中使用了,而为声明的成员是不可以被使用的。
using指示就是将一个命名空间中的所有名字全部引入到当前作用域(将命名空间在当前作用域展开)。
可能会存在命名冲突的问题。
using namespace std; //我们常用的std命名空间展开