3.7 类型转换
在 C++ 中,类型转换是将一种数据类型的值转换为另一种数据类型的过程。C++ 提供了多种类型转换方式,主要分为隐式类型转换和显式类型转换。
隐式类型转换
隐式类型转换也称为自动类型转换,是由编译器自动完成的,不需要程序员手动干预。
#include <iostream>
// 定义一个函数,用于打印整数
void printNumber(int num) {
std::cout << "传入函数的数字: " << num << std::endl;
}
int main() {
// 算术运算中的类型提升示例
int a = 10;
double b = 3.14;
// 在加法运算中,int 类型的 a 会自动转换为 double 类型
double result = a + b;
std::cout << "算术运算结果(类型提升): " << result << std::endl;
// 赋值时的类型转换示例
double num = 3.14;
// double 类型的 num 会自动转换为 int 类型,小数部分丢失
int integerNum = num;
std::cout << "赋值转换后的整数: " << integerNum << std::endl;
// 函数调用时的类型转换示例
short s = 10;
// short 类型的 s 会自动转换为 int 类型传递给函数
printNumber(s);
return 0;
}
1.算术运算中的类型提升
在进行算术运算时,如果操作数的类型不同,编译器会将较低类型提升为较高类型,以确保运算的准确性。类型提升的顺序大致为:char
/short
-> int
-> long
-> long long
-> float
-> double
。
2.赋值时的类型转换 当将一个值赋给不同类型的变量时,编译器会尝试进行隐式类型转换。如果目标类型能够容纳源类型的值,则转换成功;否则可能会导致数据丢失。
3.函数调用时的类型转换 在函数调用时,如果实参的类型与形参的类型不匹配,编译器会尝试进行隐式类型转换。
在程序代码3-5中我们清楚的演示了以上三种隐式类型转换的案例,在这个案例中 int
类型的 a
会自动转换为 double
类型。double
类型的 num
会自动转换为 int
类型但会丢失小数部分。short
类型的 s
也会自动转换为 int
类型传递给函数 printNumber
。
显式类型转换
C++ 还允许通过强制类型机制显式的进行类型转换,显式类型转换也称为强制类型转换,需要程序员手动指定转换的类型。(C++ 必须有类型规则,而有时候又需要推翻这些死板的规则)。C++ 提供了四种显式类型转换操作符,这将在第15章详细介绍,这里先进行简单说明。
1.static_cast
static_cast
用于基本数据类型之间的转换,以及具有继承关系的类对象指针或引用之间的转换。它在编译时进行类型检查,不进行运行时的类型检查。
2.dynamic_cast
dynamic_cast
主要用于具有继承关系的类对象指针或引用之间的安全向下转换(将基类指针或引用转换为派生类指针或引用)。它在运行时进行类型检查,如果转换不安全则返回空指针(对于指针转换)或抛出 std::bad_cast
异常(对于引用转换)。
3.const_cast
const_cast
用于去除变量的 const
或 volatile
限定符。它只能用于改变对象的常量性或易变性,不能用于改变对象的类型。
4.reinterpret_cast
reinterpret_cast
用于进行最底层的类型转换,它可以将一个指针转换为任意其他类型的指针,也可以将整数类型转换为指针类型。这种转换非常危险,因为它不进行任何类型检查,可能会导致未定义行为。
旧式强制类型转换
扩展阅读
C 风格的强制类型转换
这是从 C 语言继承过来的强制类型转换方式,其基本格式为:
(type)expression
在 C++ 中,还可以使用类似于 C 语言的旧式强制类型转换,语法为 (type)expression
。这种转换方式比较简单,但不够安全,因为它会尝试进行各种可能的类型转换,容易导致意外的结果。
#include <iostream>
int main() {
double num = 3.14;
int integerNum = (int)num; // 旧式强制类型转换
std::cout << "Integer number: " << integerNum << std::endl;
return 0;
}
综上 C++ 中的类型转换提供了多种方式,你可以根据具体的需求选择合适的类型转换方法。在进行类型转换时,要注意避免数据丢失和未定义行为,尽量使用安全的类型转换操作符。