C/C++ 四种 Cast 类型转换

目录

[toc]

介绍

C++ 中经常使用到类型转换,像把 int 类型转换成 char 类型,int 类型转换成 double 类型,这些转换属于隐式类型转换。这里介绍的主要是显式类型转换。C++ 提供四种显式类型转换,static_cast、dynamic_cast、const_cast、reinterpret_cast。

static_cast

static_cast 定义为:

c++ 复制
static_cast<type_name>(expression)

static_cast 一般用于隐式转换,当 type_nameexpression 至少有一方可以隐式转换时,则可以用 static_cast 进行强制类型转换。可以用于常见的 int、float、double 等类型转换,转换成功返回 true,失败返回 false(相当于C语言中的强制类型转换)。

基本类型转换

指针和 void 指针的转换

父类指针到子类指针的转换

注意:用 static_cast 进行向下转换是不安全的

dynamic_cast

定义为:

c++ 复制
dynamic_cast<type_name>(expression)

dynamic_cast 一般用户基类指针指向派生类的强制转换,成功返回 true,失败返回 false。它是安全的,安全性体现在 RTTI

RTTI 是运行时类型识别。程序能够使用基类的指针或者引用来检查其所指向的对象的实际派生类型(判断指针原型)。RTTI 提供了两个非常有用的操作符:typeiddynamic_cast 。typeid 函数为 type_info 类的友元函数,目的是为了防止创建 type_info 对象。typeid 函数的主要作用就是让用户知道当前的变量是什么类型的,它可以返回一个 type_info 的引用,可以获取类的名称和编码,typeid 重载了 type_info 中的 == 和 != 操作符,可以用来判断两个类型是否相等。

const_cast

定义为:

c++ 复制
const_cast<type_name>(expression)

const_cast 有两个功能,分别是去掉 const 和加上 const。一般用户去掉 const,修改被 const 修饰为常量的值。但是修改的这个值本身不能是 const 常量,而是被二次引用或者传参时候被引用为 const 才能修改,否则会修改失败。同时,type_name 和 expression 两个类型要一直去掉 const。

加上 const

c++ 复制
int *p = new int(2);
const int *p1 = const_cast<const int *>(p); // 转换成 const 修饰的指针

去掉 const

const 修饰指针,指向一个类对象(常量指针)

将一个常量指针转换为一个非常量指针。

c++ 复制
class A {}
class B : public A {}

int main() 
{
    A a;
    const A *p = &a;
    A *p1 = const_cast<A*>(p); // 强制将 const A* 转换成 A*
}

const 修饰指针指向对象的值(指针常量)

将指针常量,转换为非指针常量。

c++ 复制
void main()
{
    A a;
    A * const p = &a;
    A *p1 = const_cast<A*>(p); // 强制将 A * const 转换为 A *
}

const 修饰指针,且修饰指针指向的对象(常量指针常量)

c++ 复制
void main()
{
    A a;
    const A * const p = &a;
    A * p1 = const_cast<A*>(p); // 将 const A * const 强制转换为 A *
    const A * p2 = const_cast<A*>(p); // 将 const A* const 强制转换为 const A*
    A * const p3 = const_cast<A*>(p); // 将 const A* const 强制转换为 A* const
}

reinterpret_cast

定义为:

c++ 复制
reinterpret_cast<type_name>(expression)

reinterpret_cast 是一种粗暴的转换方式,并且是最不安全的。它可以把一个指针转换成整数,也可以把一个整数转换成指针(通过拷贝底层二进制数据的方式)。或者不同指针类型间的相互转换。

c++ 复制
double num = 1.5;
char *pchar = reinterpret_cast<char*>(&num); // 将 int* 转换成一个 char*
double *pdouble = reinterpret_cast<double*>(&num); // 将 int* 转换成一个 double*
std::cout << *pdouble << std::endl; // 结果为 1.2

int *pint = reinterpret_cast<int*>(&num); // 将 int* 转换成 int*
double *pdouble1 = reinterpret_cast<double*>(pint); // 将 int* 转换为 double*
std::cout << *pdouble << std::endl; // 结果为1.2

可以看到,reinterpret_cast 将 double 类型转换为 int 类型,在将 int 类型转换为 double 类型后,精度不会丢失,而 static_cast 会丢失精度。