一、概述
- 类型转换(cast)是将一种数据类型转换成另一种数据类型。例如,如果将一个整型值赋给一个浮点类型的变量,编译器会暗地里将其转换成浮点类型(即 隐式转换 )。转换是非常有用的,但是它也会带来一些问题,比如在转换指针时,我们很可能将其转换成一个比它更大的类型,但这可能会破坏其他的数据。应该小心类型转换,因为转换也就相当于对编译器说:忘记类型检查,把它看做其它的类型。一般情况下,尽量少的去使用类型转换,除非用来解决非常特殊的问题。
- 无论什么原因,任何一个程序如果使用很多类型转换都值得怀疑。
- 标准 C++ 提供了一个 显式转换 的语法,来替代旧的 C语言 风格的类型转换。使用 C语言 风格的 强制类型转换 可以把想要的任何东西转换成我们需要的类型。那为什么还需要一个新的 C++ 类型的强制转换呢?新类型的强制转换可以提供更好的控制强制转换过程,允许控制各种不同种类的强制转换。C++ 风格的强制转换其它的好处是,它们能更清晰的表明它们要干什么。程序员只要扫一眼这样的代码,就能立即知道其强制转换的目的。
- 这种 显示转换 的语法有四种,它们分别是:static_cast,dynamic_cast,const_cast和reinterpret_cast。
1、静态转换(static_cast)
- 用于类层次结构中基类(父类)和派生类(子类)之间指针或引用的转换。
- 用于 上行转换1,是安全的。
- 用于 下行转换2,由于没有动态类型检查,所以是不安全的。
- 用于基本数据类型之间的转换,如把 int 转换成 char,把 char 转换成 int。这种转换的安全性需要开发人员来保证。
2、动态转换(dynamic_cast)
- dynamic_cast 主要用于类层次间的 上行转换1 和 下行转换2 。
- 在类层次间进行 上行转换1 时,dynamic_cast 和 static_cast 的效果是一样的。
- 在进行 下行转换2 时,dynamic_cast 具有类型检查的功能,比 static_cast 更安全。
3、常量转换(const_cast)
- 该运算符用来修改类型的 const 属性。
- 常量指针被转化成非常量指针,并且仍然指向原来的对象;
- 常量引用被转换成非常量引用,并且仍然指向原来的对象;
- 注意:不能直接对非指针和非引用的变量使用 const_cast 操作符去直接移除它的 const。
4、重新解释转换(reinterpret_cast)
- 这是最不安全的一种转换机制,最有可能出现问题。
- 主要用于将一种数据类型从一种类型转换为另一种类型。它可以将一个指针转换成一个整数,也可以将一个整数转换成一个指针。
二、我自己对四种转换的总结整理
-
C语言强制类型转换,支持任意类型之间的转换,虽然用起来非常方便,但这种操作是极其不安全的。
-
下例子中用到的类的声明和定义如下:
class Animal{ cout<<"I'm a Animal."; }; //动物类 class Cat : public Animal{ cout<<"I'm a Cat."; }; //猫 class Apple{ cout<<"I'm a Apple"; }; //苹果
-
注:下面所有示例代码中的注释,
OK
表示这行代码可以正常编译通过,Error
表示报错/编译不通过
1、static_cast
-
主要用于父类和子类之间指针或引用的转换。
-
支持基本类型之间的转换。
//static_cast 作用于基本数据类型 char ch='c'; double d1=(double)ch; //C语言强制类型转换,OK double d2=static_cast<double>(ch); //静态转换,OK
-
支持 上行转换1 ,是安全的。
//static_cast 作用于自定义类型(结构体、类) //作用于有关系的类(父类和子类)之间 //1.上行转换(安全) Animal *animal=static_cast<Animal *>(new Cat); //静态转换,OK
-
支持 下行转换2 ,是不安全的。
//static_cast 作用于自定义类型(结构体、类) //作用于有关系的类(父类和子类)之间 //2.下行转换(不安全,容易访问越界) Cat *cat=static_cast<Cat *>(new Animal); //静态转换,OK
-
不支持没有关系的类之间的指针或引用的转换,保证了安全性。
Animal *animal_1=(Animal *)(new Apple); //C语言强制类型转换,OK(不安全) Animal *animal_2=static_cast<Animal *>(new Apple); //静态转换,Error
2、dynamic_cast
-
主要用于父类和子类之间指针或引用的转换。
-
不支持基本类型之间的转换。
char ch = 'c'; double d1 = (double)ch; //C语言强制类型转换,OK double d2 = dynamic_cast<double>(ch); //动态转换,Error
-
支持 上行转换1 ,是安全的。
Animal *animal=dynamic_cast<Animal *>(new Cat); //动态转换,OK
-
不支持 下行转换2 ,相比 static_cast 保证了安全性。
Cat *cat=dynamic_cast<Cat *>(new Animal); //动态转换,Error
-
不支持没有关系的类之间的指针或引用的转换,保证了安全性。
Animal *animal=dynamic_cast<Animal *>(new Apple); //动态转换,Error
3、const_cast
-
用于修改类型的const属性。
int *p=nullptr; const int *p1=(const int *)p; //C语言强制类型转换,OK const int *p2=const_cast<const int *>(p); //常量转换,OK
-
常量指针转非常量指针,仍指向原来的对象。
const int *p=nullptr; int *p1=p; //直接转换(隐式转换),Error int *p2=(int *)p; //C语言强制类型转换,OK int *p3=const_cast<int *>(p); //常量转换,OK
-
常量引用转非常量引用,仍指向原来的对象。
int num=10086; //常量引用转普通引用(非常量引用) const int &ob=num; int &ob2=ob; //直接转换(隐式转换),Error int &ob3=(int &)ob; //C语言强制类型转换,OK int &ob4=const_cast<int &>(ob); //常量转换,OK
-
不能对非指针或非引用的变量用const_cast移除它的const属性。
const int a=10086; int b=a; //直接转换(隐式转换),OK int b1=(int)a; //C语言强制类型转换,OK int b2=const_cast<int>(a); //常量转换,Error
4、reinterpret_cast
-
是最不安全的的一种类型转换方式,顾名思义,就是将一种类型转换为另一种类型,比如int转为int*,int*转为int(类似于C语言强制类型转换,但不完全相同)。
-
不支持基本类型间的转换。
char ch='c'; double d1=(double)ch; //C语言强制类型转换,OK double d2=reinterpret_cast<double>(ch); //重新解释转换,Error
-
支持不相关类型间的转换,不安全。
Animal *p=reinterpret_cast<Animal *>(new Apple); //重新解释转换,OK
-
支持 上行转换1 ,安全。
Animal *p=reinterpret_cast<Animal *>(new Cat); //重新解释转换,OK
-
支持 下行转换2 ,不安全。
Cat *cat=reinterpret_cast<Cat *>(new Animal); //重新解释转换,OK
三、脚注与版权声明
以上部分内容引用自千峰梁何大佬的课件,仅供参考学习,侵删。
参考链接:6.00 static cast静态转换_bilibili。
如有错误或者遗漏的地方欢迎各位大佬补充指正!
创建日期:2022年08月20日 AM.