IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> 猿创征文|[C++ 从入门到精通] 6.static_cast、dynamic_cast等显示类型转换 -> 正文阅读

[C++知识库]猿创征文|[C++ 从入门到精通] 6.static_cast、dynamic_cast等显示类型转换

  • 📢博客主页:https://loewen.blog.csdn.net
  • 📢欢迎点赞 👍 收藏 ?留言 📝 如有错误敬请指正!
  • 📢本文由 丶布布原创,首发于 CSDN,转载注明出处🙉
  • 📢现在的付出,都会是一种沉淀,只为让你成为更好的人?


一. 隐式类型转换

含义:隐式类型转换:系统自动进行,不需要开发人员介入。

int m = 3 + 45.6;      //48     

因为返回的int型,所以系统自动去除掉小数点后面的值,结果为48,这种属于隐式转换类型。


二. 显式类型转换(强制类型转换)

1、C语言的强制类型转换风格:

//int k = 5 % 3.2;     //语法错误:%非法,右操作数包含“double”类型
int k = 5 % int(3.2);  //将3.2强制转换成int型3,C语言风格的强制类型转换,结果:余2   

上面这种C语言的强制类型转换风格,没有类型检查,往整型上硬转,转的对不对需要程序员提供保障,例如强制将字符串类型转换成int类型:(int)"asa"就不行了。

2、针对上面的情况,C++提供了4种更为安全的强制类型转换:

  • static_cast显式转换类型;
  • dynamic_cast显式转换类型;
  • const_cast显式转换类型;
  • reinterpret_cast显式转换类型;

C++强制类型转换通用书写形式:强制类型转换名 <type> ( express );

  • 强制类型转换名static_castdynamic_castconst_castreinterpret_cast4种类型
  • type:转换到的目标类型
  • express:待转换的类型(值或变量),即express转换成type类型

每一种强制类型转换都有其特定的目的,这样可以提供更丰富的含义和功能、更好的类型检查机制,方便代码的编写和维护。


static_cast显示转换

含义: static_cast静态转换,理解成“正常转换”(编译时进行类型检查)。

适用场合:

1、相关类型转换,比如整型int和实型qeal之间的转换。

double f = 100.34;

int ic1 = f;                     //方式一:隐式转换直接转
int ic1 = int(f);                //方式二:C风格的强制类型转换
int ic2 = static_cast<int>(f);   //方式三:C++风格的强制类型转换

2、继承关系中子类转换成父类类型(向上转换:隐式转换),可以直接转换,也可以使用static_cast转。

class A {};
class B : public A {};

A a;
B b;
a = b;                  //方式一:隐式转换直接转
a = static_cast<A>(b);  //方式二:static_cast转换

3、void *与其他类型指针之间的转换。void *:无类型指针(万能指针):可以指向任何指针类型

int i = 10;
int *p = &i;
void *q = p;                       //方式一:隐式转换,系统内部自己转
void *q = static_cast<void *>(p);  //方式二:static_cast转换

不适用场合:

1、指针类型之间的转换,比如int *double *double *float *等。

double d = 100.34;
double *pd = &d;
int *pi = static_cast<int *>(pd);   //达咩,类型转换无效

小结:static_cast含义跟C语言中的强制类型转换差不多:

  • C风格的强制类型转换编译器自己能够进行的隐式类型转换都可以用static_cast显示完成转换(一般隐式转换让系统内部自己转就好了,不需要static_cast转换)。
  • C风格的强制类型转换一样,使用static_cast也要保证转换的安全性和正确性,比如int i = (int)“asa”这种情形不应该出现。

dynamic_cast显示转换

含义: dynamic_cast:能够将基类指针引用安全的转换为派生类的指针引用(运行时进行类型检查)。

ps:只要dynamic_cast运算符能转换成功,就说明这个指针实际上是要转换到的那个类型,否则不能转换成功。这也间接的帮助我们完成了运行时的类型识别和安全检查(弥补C语言风格的强制转换式的不足)。

适用场合:

1、有继承关系父类指针转换成子类指针(向下显示转换)

struct Father{ /*父类Father*/ };
struct Son: Father{ /*基类Father的子类B*/ };
        
Father *father = new Son;
Son *son = (Son *)(father);  //C风格的强制类型转换:硬把父类指针Father *转换成子类指针Son *,可以
//son->子类成员               //可以,能够正常调用Son类的成员函数

这种转换需要我们明确父类指针father是指向子类Son对象的(Father *father = new Son)才是安全的。否则明明father是指向Son对象的,却被强制转换成其他类的指针,再调用就不安全了。此外,如果在他人的代码中看到一个指针father,想要确认这个指针到底是指向本身类Father对象的、子类Son对象还是其他类的对象就太好区分,所以应该使用dynamic_cast来完成父类指针到子类指针的强制转换:

struct Father{ /*父类Father*/ };
struct Son: Father{ /*基类Father的子类B*/ };
        
Father *father = new Son; 
Son *son =  dynamic_cast<Son *>(father);
if (son != nullptr)     //对于引用,如果用dynamic_cast转换失败,系统会抛出std::bad_cast异常
{
    cout << "father实际是一个Son类型" << endl;  //在这里操作Son里面的成员函数、成员变量都能够操作并且安全的操作
}

注意:使用dynamic_cast显示转换父类指针时要保证父类中一定要有虚函数virtual,否则会报错:运行dynamic_cast操作符必须包含多态类类型。

2、有继承关系父类引用转换成子类引用(用的较少,了解)

struct Father{ /*父类Father*/ };
struct Son: Father{ /*基类Father的子类B*/ };
 	      
Father *father1 = new Son;
Father &father2 = *father1;
try
{
    Son &son = dynamic_cast<Son &>(father2);    //转换成功
}
catch (std::bad_cast)
{
    cout << "father2实际不是一个Son类型" << endl;
}

const_cast显示转换

含义:const_cast去除指针或引用的const属性。该转换能够将const性质转换掉或去除掉(编译时进行类型检查)。

错误示范:

const int ai = 90;
int ai2 = const_cast<int>(ai);

结果:

在这里插入图片描述
正确示范:

const int ai = 90;
const int *ai2 = &ai;
int *ai3 = const_cast<int *>(ai2);   //截止到这里都没问题
*ai3 = 120;  //注意:这种写值行为是一种未定义行为(实际结果不可控,因为*ai3转换之前是常量const int ai,所以不要往里写值,正常调用指针对象没问题)

reinterpret_cast显示转换

reinterpret_cast 处理无关类型之间的转换,也就是两个转换类型之间没有什么关系,就等于可以乱转、自由转,非常随意(编译时进行类型检查)

ps: reinterpret:重新解释,将操作数内容解释为另一种不同的类型(能把操作数的类型都转了)。

适用场合:

1、将一个整型(地址)转换成指针,一种类型指针转换成另一种类型指针,按照转换后的类型重新解释内存中的内容。

2、将一个指针类型转换成一个整型。

int i = 10;
int *p= &i;

int *pi = reinterpret_cast<int *>(&i);    //这个没啥说的
char *pc = reinterpret_cast<char *>(p);   //int *也可以转换成char *,语法对,但是没什么屌用

ps:reinterpret_cast被认为是危险的类型转换,虽然其可以随便转换,而且编译器也不报错,但是需要合乎规则的用,不然就没什么意义了。这里了解一下,防止看别人代码不知道什么意思。


三. 总结

  1. 所有强制类型转换,不建议使用,强制类型转换能够抑制编译器报错。
  2. 学习目的:认识这些类型转换符,方便大家阅读别人代码。
  3. 资料说:reinterpret_cast危险,我们需要合乎规则的用,不要乱用;使用const_cast意味着设计缺陷。
  4. 如果实在需要使用强制类型转换,不要再使用C语言风格的类型转换了,而是用上面C++风格的类型转换,一般static_castreinterpret_cast能够很好的取代C语言风格的强制类型转换。

下雨天,最惬意的事莫过于躺在床上静静听雨,雨中入眠,连梦里也长出青苔。
  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-09-04 00:51:43  更:2022-09-04 00:53:03 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/14 3:15:39-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码