C++ 类型转换与推导总结测验
- 类型转换:把某值由一种数据类型变为另一种数据类型的过程称为“类型转换”。
- 隐式类型转换(implicit type conversion,又称自动转换或 coercion):当代码要求某类型却提供了另一类型时,若编译器知道如何转换,则自动完成;否则编译报错。
- 标准转换:C++ 内置的一系列转换规则,涵盖基本类型及部分高级类型,包括数值提升、数值转换与算术转换。
- 数值提升(numeric promotion):把某些较小数值类型转换为较大数值类型(通常为 int或double),使 CPU 能以自然字长高效运算。含整型提升与浮点提升,保值且无精度损失;并非所有加宽转换都是提升。
- 数值转换(numeric conversion):除数值提升外的基本类型间转换。
- 窄化转换(narrowing conversion):可能导致值或精度损失的数值转换。
- 算术转换(usual arithmetic conversions):某些二元运算符要求操作数同类型,编译器按规则隐式转换。
- 显式类型转换:程序员用 强制转换(cast)显式要求转换。C++ 提供 5 种 cast:C 风格 cast、static_cast、const_cast、dynamic_cast、reinterpret_cast。一般应避免前三种;static_cast最常用。
- typedef 与类型别名:为类型创建别名,并非新类型,与原类型完全等价,无额外类型安全。
- auto:- 用于变量,可根据初始化式 类型推导(type deduction)。推导结果会丢弃顶层 const和引用,需要时应手动添加。
- 用于函数返回类型,可让编译器根据 return语句推导;但普通函数建议显式返回类型。亦可用于 尾随返回类型语法。
 
- 用于变量,可根据初始化式 类型推导(type deduction)。推导结果会丢弃顶层 
小测
问题 1
下列语句各发生何种转换?可选答案:无需转换、数值提升、数值转换、因窄化转换无法编译。假设 int 与 long 均为 4 字节。
int main()
{
    int  a { 5 };                      // 1a
    int  b { 'a' };                    // 1b
    int  c { 5.4 };                    // 1c
    int  d { true };                   // 1d
    int  e { static_cast<int>(5.4) };  // 1e
    double f { 5.0f };                 // 1f
    double g { 5 };                    // 1g
    // 附加题
    long  h { 5 };                     // 1h
    float i { f };                     // 1i(使用前述变量 f)
    float j { 5.0 };                   // 1j
}
答案
1a. 无需转换
1b. 数值提升(char → int)
1c. 因窄化转换无法编译
1d. 数值提升(bool → int)
1e. 数值转换(double → int)
1f. 数值提升(float → double)
1g. 数值转换(int → double)
1h. 数值转换(int → long)
1i. 数值转换(double → float,且因窄化无法编译)
1j. 数值转换(double → float,且因窄化无法编译)
问题 2
2a) 改写下列程序,使用类型别名表示“度”与“弧度”:
#include <iostream>
namespace constants
{
    constexpr double pi { 3.14159 };
}
double convertToRadians(double degrees)
{
    return degrees * constants::pi / 180;
}
int main()
{
    std::cout << "Enter a number of degrees: ";
    double degrees{};
    std::cin >> degrees;
    double radians { convertToRadians(degrees) };
    std::cout << degrees << " degrees is " << radians << " radians.\n";
    return 0;
}
参考答案
#include <iostream>
namespace constants
{
    constexpr double pi { 3.14159 };
}
using Degrees = double;
using Radians = double;
Radians convertToRadians(Degrees deg)
{
    return deg * constants::pi / 180;
}
int main()
{
    std::cout << "Enter a number of degrees: ";
    Degrees degrees{};
    std::cin >> degrees;
    Radians radians { convertToRadians(degrees) };
    std::cout << degrees << " degrees is " << radians << " radians.\n";
    return 0;
}
2b) 根据上题别名定义,解释为何下列语句能否通过编译:
radians = degrees;
解释:
Radians 与 Degrees 均为 double 的别名,本质相同,因此赋值语法正确,编译通过。但语义上把“度”直接赋给“弧度”可能不符合逻辑,需由程序员自行确保正确性。
