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
的别名,本质相同,因此赋值语法正确,编译通过。但语义上把“度”直接赋给“弧度”可能不符合逻辑,需由程序员自行确保正确性。