10-x 第十章总结与测验

能坚持到这里很棒。标准转换规则相当复杂——不必担心无法理解每个细节。


章节回顾

将值从一种数据类型转换为另一种数据类型的过程称为类型转换type conversion

隐式类型转换implicit type conversion(也称自动类型转换automatic type conversion强制转换coercion)发生在预期某种类型的数据时,却被提供不同类型数据的情况。若编译器能确定两种类型间的转换方式,则会自动执行转换;若无法确定,则会报编译错误。

C++语言定义了基础类型间的多项内置转换(以及部分高级类型的转换),称为标准转换standard conversions。这些转换包括数值提升、数值转换和算术转换。

数值提升numeric promotion是指将特定较小数值类型转换为特定较大数值类型(通常为 int 或 double),以便 CPU 能处理与处理器自然数据尺寸匹配的数据。数值提升包含整数提升和浮点提升两种形式。数值提升具有值保留特性value-preserving,即不会导致数值或精度损失。并非所有拓宽转换都属于提升。

数值转换numeric conversion是指基本类型间不属于数值提升的类型转换。窄化转换narrowing conversion属于数值转换,可能导致数值或精度损失。

在C++中,某些二元运算符要求其操作数类型一致。若提供不同类型的操作数,则会根据称为常规算术转换usual arithmetic conversions的规则集,将一个或两个操作数隐式转换为匹配类型。

显式类型转explicit type conversion换发生于程序员通过强制转换显式请求转换时。强制转换cast代表程序员要求执行显式类型转换。C++支持五种强制转换类型:C风格强制转换C-style casts、静态强制转换static casts、const强制转换const casts、动态强制转换dynamic casts和reinterpret强制转换reinterpret casts。通常应避免使用C风格转换、const转换和reinterpret转换。static_cast用于将值从一种类型转换为另一种类型,是C++中最常用的转换方式。

类型定义typedef类型别名type aliases允许程序员为数据类型创建别名。这些别名并非新类型,其行为与被别名类型完全一致。类型别名不提供任何类型安全保障,需谨慎避免将别名与原始类型混淆。

auto 关键字具有多重用途:首先可用于类型推断type deduction(也称类型推导type inference),即根据初始化表达式推断变量类型。类型推断会忽略 const 和引用修饰符,若需保留这些修饰符请手动添加。

Auto 也可用作函数返回类型,让编译器根据函数的返回语句推断其返回类型,但普通函数应避免使用此方式。Auto 作为尾随返回语法trailing return syntax的一部分使用。


测验时间

问题 #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

    // Extra credit section
    long h { 5 }; // 1h

    float i { f }; // 1i (uses previously defined variable f)
    float j { 5.0 }; // 1j

}

1a) 显示答案

无需转换

1b) 显示答案

将字符‘a’数值提升为整型

1c) 显示答案

由于窄化转换,无法编译

1d) 显示答案

将布尔值 true 提升为整数类型

1e) 显示答案

将双精度浮点数5.4转换为整型

1f) 显示答案

将浮点数强制提升为双精度类型

1g) 显示答案

将整型数转换为双精度浮点数

1h) 显示答案

将整型数转换为长整型数(此转换虽简单,但仍属于数值转换操作)

1i) 显示答案

由于从 double 到 float 的窄化转换,无法编译

1j) 显示答案

将double数值转换为float(此操作在5.0版本中被允许,因为constexpr且结果值在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 degrees)
{
    return degrees * 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 的类型是 Radians,这是 double 的类型别名。degrees 的类型是 Degrees,同样是 double 的类型别名。因此这只是将 double 值赋给 double 类型的变量。
posted @ 2026-03-05 11:35  游翔  阅读(2)  评论(0)    收藏  举报