[C++] 类型转换

类型转换

在C++语言中,某些类型之间有关联,如果两种类型有关联,那么当程序需要其中一种类型的运算对象时,可以用另一种关联类型的对象或值来替代。换句话说,如果两种类型可以相互转换,那么它们就是关联的。

例如

int ival = 3.14 + 3;
// 3.14 + 3 = 6 : double + int ~ double
// ival = 6 : double ~ int

何时发生隐式转换

1、在大多数表达式中,比int类型小的整型值首先提升为较大的整数类型

2、在条件中,非布尔值转换成布尔类型

3、初始化过程中,初始值转换成变量的类型;在赋值语句中,右侧运算对象转换成左侧运算对象的类型。

4、如果算术运算或关系运算的运算对象有多种类型,需要转换成同一种类型。

5、函数调用时也会发生类型转换

算术转换

算术转换的含义是把一种算术类型转换成另外一种算术类型,

其中:运算符的运算对象将转换成最宽的类型;当表达式中既有浮点类型也有整数类型时,整数值将转换成相应的浮点类型

整型提升

整型提升负责把小整数类型转换成较大的整数类型。要求转换后的类型要能容纳原类型所有可能的值

无符号类型的运算类型

如果某个运算对象的类型是无符号类型,那么转换的结果就要依赖于机器中各个整数类型的相对大小

首先要进行整型提升,如果带符号的类型不大于无符号的类型,然后对于有符号的数转换成无符号的数。如果带符号的类型大于无符号的类型,那么转换的结果依赖于机器。

其他隐式类型转换

数组转换成指针

数组是自动转换成指向数组首元素的指针

int ia[10];
// 含有10个整数的数组
int* p = ia;
// ia转换成指向数组首元素的指针

decltype、&、sizeof、typeid等运算符操作时,上述转换不会发生

如果用一个引用来初始化数组,上述转换也不会发生。

指针的转换

常量整数值或字面值nullptr能转换成任意指针类型

指向任意非常量的指针能转换成void*

指向任意对象的指针能转换成const void*

还存在继承类型关系间的指针转换

转换成布尔类型

如果指针或算术类型的值为0,转换结果是false。

转换成常量

允许将指向非常量类型的指针转换成指向相应的常量类型的指针,对于引用也是这样。

如果T是一种类型,我们就能将指向T的指针或引用分别转换成指向const T的指针或引用。

int i;
const int &j = i;
// 非常量转换成const int的引用
const int *p = &i;
// 非常量的地址转换成const的地址
int &r = j, *q = p;
// 错误,不允许const转换成非常量

相反的转换不存在,因为它试图删除掉底层const

类类型定义的转换

类类型能定义由编译器自动执行的转换,不过编译器每次只能指向一种类类型的转换。

string s, t  = "a value";
// 字符串字面值转换成string类型

显式转换

显式将对象强制转换成另外一种对象

强制类型转换如浮点数除法,

int i, j;
double slope = i / j;
// 将i和/或j显式转换成double

命名的强制类型转换

cast-name<type>(expression);

type: 转换的目标类型

expression: 要转换的值

如果type是引用类型,则结果是左值。

cast-name: static_cast、dynamic_cast、const_cast、reinterpret_cast

static_cast

任何具有明确定义的类型转换,只要不包含底层const,都可以使用static_cast

double slope = static_cast<double>(j) / i;
// 进行强制类型转换以便执行浮点数除法

当需要把一个较大的算术类型赋值给较小的类型时,static_cast非常有用

如果不使用static_cast则会给出警告信息,

static_cast对于编译器无法自动执行的类型转换非常有用

可以用static_cast找回存在于void*指针中的值。

void* p = &d;
// 任何非常量对象的指针都能存入void*

double *dp = static_cast<double*>(p);
// 正确,将void*转换回初始的指针类型

在转换时要确保指针的值保持不变,也就是说强制转换的结果将与原始的地址值相等。

const_cast

const_cast只能改变运算对象的底层const

const char *pc;
char *p = const_cast<char*>(pc);

对于常量对象转换成非常量对象的行为,我们一般称为去掉const性质。

如果对象本身不是一个常量,使用强制类型转换获得写权限是合法的行为

如果对象本身是一个常量,使用强制类型转换执行写操作就会产生未定义的后果。

const char *cp;
char *q = static_cast<char*>(cp);
// 错误,static_cast不能转换掉const性质
static_cast<string>(cp);
// 正确:字符串字面值传换成string类型
const_cast<string>(cp);
// 错误:const_cast只改变常量属性

reinterpret_cast

reinterpret_cast常为运算对象的位模式提供较低层次上的重新解释

int *ip;
char *pc = reinterpret_cast<char*>(ip);
// pc所指的真实对象是一个int而非字符,如果把pc当作普通的字符指针使用就可能在运行时发生错误
string str(pc);
// 导致异常
原文地址:https://www.cnblogs.com/immjc/p/8044220.html