在 C++ 中,using 是一个关键字,用来为已有数据类型创建别名。语法为:
using 别名 = 原类型;
例如:
using Distance = double;   // 将 Distance 定义为 double 的别名
定义完成后,即可在任何需要类型的地方使用该别名:
Distance milesToDestination{ 3.4 };   // 实际类型为 double
编译器遇到别名时,会用原类型替换。示例:
#include <iostream>
int main()
{
    using Distance = double;
    Distance milesToDestination{ 3.4 };
    std::cout << milesToDestination << '\n';   // 输出 3.4
    return 0;
}
供进阶读者
类型别名亦支持模板化,见 —— 类模板实参推导(CTAD)与推导指引。
类型别名的命名惯例
历史上命名方式并不统一,常见有三种:
- 以 _t结尾(如size_t、nullptr_t),继承自 C,但现代 C++ 已不推荐;POSIX 保留全局_t后缀,可能产生冲突。
- 以 _type结尾(如std::string::size_type),但同样存在不一致。
- 无后缀,首字母大写。现代 C++ 推荐用 PascalCase 命名自定义类型,以区分变量/函数名(小写开头)并避免碰撞。
示例:
void printDistance(Distance distance);
Distance 是类型,distance 是形参名,C++ 区分大小写,合法且清晰。
最佳实践
自定义类型别名使用首字母大写且无后缀(除非有特定理由)。
作者注
本教程部分旧课仍用 _t/_type,欢迎指出以便统一。
类型别名并非新类型
别名只是为原类型引入新标识符,不创建独立类型,二者完全可互换。因此可能出现语法正确但语义荒谬的代码:
int main()
{
    using Miles = long;
    using Speed = long;
    Miles distance{ 5 };
    Speed mhz{ 3200 };
    distance = mhz;   // 合法,但语义错误
}
编译器仅看到 long 到 long,不会阻止此类错误,故别名不具备类型安全;尽管如此,它们仍有益处。
警告
务必避免混用语义本应不同却共享同一别名的值。
附注
部分语言支持强 typedef(strong typedef),会生成真正的新类型,混用时报错。C++20 无原生支持,但可用第三方库实现;enum class 与之类似。
类型别名的作用域
作用域规则与变量相同:块内定义的别名仅在该块可见;全局定义则文件内可见。若需在多文件使用,可放在头文件:
mytypes.h
#ifndef MYTYPES_H
#define MYTYPES_H
using Miles = long;
using Speed = long;
#endif
通过 #include 后,别名即拥有全局作用域。
typedef
typedef 是早期创建别名的方式,语法:
typedef long Miles;   // 与 using Miles = long; 等效
为兼容 C 仍保留,但现代 C++ 推荐 using。
typedef 语法缺陷:
- 顺序易错:typedef Distance double; // 错 typedef double Distance; // 对
- 复杂类型可读性差:typedef int (*FcnType)(double, char); // 难读 using FcnType = int(*)(double, char); // 易读
- 名称“typedef”暗示“定义新类型”,实为别名。
最佳实践
优先使用类型别名(using)而非 typedef。
术语
- C++ 标准用 typedef names 统称 typedef 与类型别名。
- 日常中“typedef”常泛指两者,因功能一致。
何时使用类型别名
- 平台无关编码 - int、- long等大小随平台变化。跨平台程序常用别名包含位宽信息,如- int8_t、- int16_t、- int32_t,配合预处理器:- #ifdef INT_2_BYTES using int8_t = char; using int16_t = int; using int32_t = long; #else using int8_t = char; using int16_t = short; using int32_t = int; #endif- 标准库中的固定宽度整数( - std::int16_t、- std::uint32_t)和- size_t亦为此类别名。
- 简化复杂类型 
 例如:- using VectPairSI = std::vector<std::pair<std::string, int>>;- 大幅减少打字与错误。 
- 描述值语义 
 函数返回裸- int时语义不明:- using TestScore = int; TestScore gradeTest();- 虽仅适用于大量相关函数,否则用注释更佳。 
- 便于维护 
 若需将- short改为- long,只需修改别名:- using StudentId = long; // 原为 short- 但跨类型族修改需重测代码! 
缺点与结论
别名引入额外标识符,若未提升可读性/可维护性则弊大于利。
糟糕别名会把熟悉类型(如 std::string)藏在新名字后,甚至隐藏智能指针语义,反而有害。
最佳实践
仅在显著提升可读性或可维护性时使用别名;多位置使用优于少量使用。
小测验
问题 #1
给定函数原型:
int printData();
将其返回类型改为类型别名 PrintError,请写出类型别名定义及更新后的函数原型。
(参考答案略)
