第六章 类型与声明
6.5 类型别名
有时,我们需要为某种类型起个新名字。可能的动机包括:
- 原来的名字太长、太复杂或者太难看(在某些程序员眼中)。
- 某项程序设计技术要求在同一段上下文中,不同类型有相同的名字。
- 在某处提及某种类型仅仅是为了便于后期维护。
例如:
using Pchar = char*; //字符串指针
using PF = int(*)(double); //函数指针。该函数接受一个double且返回一个int
相似类型可以定义同一个名字作为成员别名:
template<class T>
class vector{
using value_type = T; //每个容器都有一个value_type
//...
};
template<class T>
class list{
using value_type = T; //每个容器都有一个value_type
//...
};
无论如何,类型别名绝不代表一种新类型,它只是某种已有类型的同义词。换句话说,别名就是类型的另外一个名字而已。例如:
Pchar p1 = nullptr; //p1的类型是char*
char* p3 = p1; //正确
如果你想实现一种新类型,并且它的语义和表达形式与某种已有类型一致,应该使用枚举(见8.4节)或者类(第16章)。
早期还有一种语法也可以用在类似的语境中,我们使用typedef关键字,然后把要生命的类型别名放在一般声明语句中变量所在的位置上。例如:
typedef int int32_t; //等价于“using int32_t = int;”
typedef short int16_t; //等价于“using int16_t = short;”
typedef void(*PtoF)(int); //等价于“using PtoF = void(*)(int);”
使用别名有助于我们把代码与机器细节分离开来。名字int32_t明确指出我们想用它表示占32个二进制位的整数。与“普通的int”相比,使用int32_t可以让我们把代码平滑地移植到一台sizeof(int)==2的机器上。我们要做的只是修改一处int32_t的定义令其表示一个尺寸更大的整数类型即可:
using int32_t = long;
后缀_t通常用来表示类型别名(源自typedef关键字)。int16_t、int32_t以及其他一些类型别名都定义在 < cstdint >中(见43.7节)。类型的别名应该尽可能反映出该类型的目的和作用,而不是类型的实现细节(见6.3.3节)。
using关键字可用于引入一个template别名(见23.6节),例如:
template<typename T>
using Vector = std::vector<T, My_allocator<T>>;
不允许在类型别名前加修饰符(如unsigned),例如:
using Char = char;
using Uchar = unsigned Char; //错误
using Uchar = unsigned char; //OK