【036】读懂C++的强制类型转换static_cast、const_cast、dynamic_cast以及reinterpret_cast

news2024/11/24 2:53:45

C++的强制类型转换

  • 引言
  • 一、类型转换简介
  • 二、上行、下行转换的概述
  • 三、static_cast 静态类型转换
  • 四、dynamic_cast 静态类型转换(推荐使用)
  • 五、const_cast 常量转换
  • 六、reinterpret_cast 重新解释转换(最不安全)
  • 总结

引言


💡 作者简介:专注于C/C++高性能程序设计和开发,理论与代码实践结合,让世界没有难学的技术。包括C/C++、Linux、MySQL、Redis、TCP/IP、协程、网络编程等。
👉
🎖️ CSDN实力新星,社区专家博主
👉
🔔 专栏介绍:从零到c++精通的学习之路。内容包括C++基础编程、中级编程、高级编程;掌握各个知识点。
👉
🔔 专栏地址:C++从零开始到精通
👉
🔔 博客主页:https://blog.csdn.net/Long_xu


🔔 上一篇:【035】C++泛型编程(模板)实践:设计数组类模板模仿vector容器

一、类型转换简介

标准C++提供了一个显式的转换语法,用来代替C语言风格的类型转换。使用C语言风格的强制转换可以把想要的任何东西转换成我们需要的类型。

新类型的强制转换可以提供更好的控制强制转换过程,允许控制各种不同类型的强制转换。
C++风格的强制转换的好处:能更清晰的表明它们要干什么。开发者只要看一眼这样的代码,就能够立即知道一个强制转换目的。

C++中的类型转换允许将一个数据类型转换为另一个数据类型。C++提供了多种类型转换操作符和函数来执行不同类型之间的转换。

以下是C++中常见的类型转换方式:

  1. 隐式类型转换(Implicit Type Conversion):也称为自动类型转换,是编译器隐式地执行的类型转换。这种转换是安全的,可以由编译器自动完成,无需显式指定。例如,将一个整数赋值给一个浮点数变量,编译器会自动将整数转换为浮点数。

  2. 显式类型转换(Explicit Type Conversion):也称为强制类型转换,是通过使用转换操作符或函数来显式指定类型转换的方式。显式类型转换可能会导致数据丢失或精度损失。C++提供了以下三种显式类型转换方式:

    • 静态转换(static_cast):用于基本数据类型之间的转换,以及具有继承关系的指针和引用之间的转换。
    • 动态转换(dynamic_cast):用于具有继承关系的类之间的转换,可以在运行时检查类型转换的有效性。
    • 常量转换(const_cast):用于去除指针或引用的常量属性。
  3. 重新解释转换(reinterpret_cast):用于将一个指针或引用转换为另一个不相关类型的指针或引用,这是一种非常危险的转换,需要谨慎使用。

类型转换应该在必要时使用,并且要确保转换的安全性。错误的类型转换可能导致数据丢失、不可预料的行为或程序崩溃。所以,在进行类型转换时,一定要了解数据类型的特点,并谨慎选择适当的转换方式。

二、上行、下行转换的概述

在C++中,上行转换(upcasting)和下行转换(downcasting)是指在继承关系中的类型转换。

  1. 上行转换(Upcasting):将派生类指针或引用转换为基类指针或引用。上行转换是安全的,因为派生类对象中包含了基类对象的所有成员。上行转换是隐式的,不需要显式指定,编译器会自动完成。例如,如果有一个基类Animal和一个派生类Dog,那么可以将Dog对象的指针或引用赋值给Animal对象的指针或引用。

  2. 下行转换(Downcasting):将基类指针或引用转换为派生类指针或引用。下行转换是不安全的,因为基类对象中可能没有派生类特有的成员。下行转换必须显式指定,并且需要使用dynamic_cast运算符进行类型检查。在运行时,dynamic_cast会检查转换是否有效,如果转换无效,返回空指针(对于指针)或引发std::bad_cast异常(对于引用)。例如,如果有一个基类Animal的指针或引用,可以使用dynamic_cast将其转换为派生类Dog的指针或引用。

下行转换只有在确保基类对象指向的是派生类对象时才能安全进行。否则,进行下行转换可能会导致未定义的行为或程序崩溃。因此,在进行下行转换时,最好先使用dynamic_cast进行类型检查,以确保转换的有效性。
在这里插入图片描述

三、static_cast 静态类型转换

static_cast 用于类层次结构中基类(父类)和派生类(子类)之间指针和引用的转换。它支持:

  • 基本类型。
  • 上行转换。
  • 下行转换。

不支持不相干类型转换。

假设存在这样的类:

class Base{
};
class Son:public Base{
};

class Other{
};

(1)支持基本类型。

int num=static_cast<int>(3.1415);// ok

(2)支持上行转换,安全。

Base *p=static_cast<Base *>(new Son);// ok

(3)支持下行转换,不安全。

Son *p=static_cast<Son *>(new Base);// ok

(4)不支持不相关类型的转换。

Base *p=static_cast<Base *>(new Other);// error

在这里插入图片描述

完整示例:

#include <iostream>
using namespace std;

class Base {
};
class Son :public Base {
};

class Other {
};

int main()
{
	int num = static_cast<int>(3.1415);// ok
	Base *p = static_cast<Base *>(new Son);// ok
	Son *p2 = static_cast<Son *>(new Base);// ok
	//Base *p = static_cast<Base *>(new Other);// error
	return 0;
}

四、dynamic_cast 静态类型转换(推荐使用)

dynamic_cast 主要用于类层次间的上行转换和下行转换。一种最安全的类型转换。

假设存在这样的类:

class Base{
};
class Son:public Base{
};

class Other{
};

(1)不支持基本类型。

int num=dynamic_cast<int>(3.1415);// error

(2)支持上行转换,安全。

Base *p=dynamic_cast<Base *>(new Son);// ok

(3)不支持下行转换,不安全。

Son *p=dynamic_cast<Son *>(new Base);// error

(4)不支持不相关类型的转换。

Base *p=dynamic_cast<Base *>(new Other);// error

完整示例:

#include <iostream>
using namespace std;

class Base {
};
class Son :public Base {
};

class Other {
};

int main()
{
	int num = dynamic_cast<int>(3.1415);// error
	Base *p = dynamic_cast<Base *>(new Son);// ok
	Son *p2 = dynamic_cast<Son *>(new Base);// error
	Base *p3 = dynamic_cast<Base *>(new Other);// error
	return 0;
}

报错效果:
在这里插入图片描述

五、const_cast 常量转换

语法:

const_cast< new-type expression>(...)		

返回new-type类型的值。

用途:

  • 将const修饰的指针或引用转换成非const。
  • 将非const修饰的指针或引用转换成const。
const int *p;
int *p2=const_cast<int *>(p);

const int &ob=10;
int &ob2=const_cast<int &>(ob);

int *p3;
const int *p4=const_cast<int *>(p3);

int ob3=10;
const int &ob4=const_cast<int &>(ob3);

const_cast只能进行以下转换。特别是,只有const_cast可用于抛弃(去除)恒常性或波动性。

(1)指向同一类型的两个可能的多级指针可以相互转换,而不必考虑每个级别上的cv限定符。

(2)任何类型的左值都可以转换为相同类型的左值或右值引用,或多或少受cv限制。同样,类类型的右值或任何类型的右值都可以转换为或多或少限定cv的右值引用。如果表达式是一个全局值,则引用const_cast的结果指向原始对象,否则指向物化的临时对象。

(4)同样的规则也适用于可能指向数据成员的多级指针,以及可能指向具有已知和未知边界的数组的多级指针(指向限定cv的元素的数组本身也被认为是限定cv的)。

(5)空指针值可以转换为new-type的空指针值。

示例:

#include <iostream>
 
struct type
{
    int i;
 
    type(): i(3) {}
 
    void f(int v) const
    {
        // this->i = v;                 // compile error: this is a pointer to const
        const_cast<type*>(this)->i = v; // OK as long as the type object isn't const
    }
};
 
int main()
{
    int i = 3;                 // i is not declared const
    const int& rci = i;
    const_cast<int&>(rci) = 4; // OK: modifies i
    std::cout << "i = " << i << '\n';
 
    type t; // if this was const type t, then t.f(4) would be undefined behavior
    t.f(4);
    std::cout << "type::i = " << t.i << '\n';
 
    const int j = 3; // j is declared const
    [[maybe_unused]]
    int* pj = const_cast<int*>(&j);
    // *pj = 4;      // undefined behavior
 
    [[maybe_unused]]
    void (type::* pmf)(int) const = &type::f; // pointer to member function
    // const_cast<void(type::*)(int)>(pmf);   // compile error: const_cast does
                                              // not work on function pointers
}

六、reinterpret_cast 重新解释转换(最不安全)

不支持基本类型,但是支持基本类型指针,而且其他的基本都支持,所以是最不安全的。
假设存在这样的类:

class Base{
};
class Son:public Base{
};

class Other{
};

(1)不支持基本类型,但支持基本类型指针。

int num=reinterpret_cast<int>(3.1415);// error
float *q;
int *p=reinterpret_cast<int *>(q);// ok

在这里插入图片描述

(2)支持上行转换。

Base *p=reinterpret_cast<Base *>(new Son);// ok

(3)支持下行转换。

Son *p=reinterpret_cast<Son *>(new Base);// ok

(4)支持不相关类型的转换。

Base *p=reinterpret_cast<Base *>(new Other);// ok

完整示例:

#include <iostream>
using namespace std;

class Base {
};
class Son :public Base {
};

class Other {
};

int main()
{
	int num = reinterpret_cast<int>(3.1415);// error
	float q = 3.16f;
	float *q2 = &q;
	int *num2 = reinterpret_cast<int *>(q2);// ok

	Base *p = reinterpret_cast<Base *>(new Son);// ok
	Son *p2 = reinterpret_cast<Son *>(new Base);// ok
	Base *p3 = reinterpret_cast<Base *>(new Other);// ok
	return 0;
}

总结

  1. 静态类型转换

静态类型转换是最常用的类型转换方式,它可以将一种类型的数据强制转换为另一种类型,但需要注意的是,这种转换可能会损失一些信息,因此在进行此类转换时应当谨慎。

例如:

int a = 10;
double b = static_cast<double>(a);
  1. 动态类型转换

动态类型转换主要用于多态类型之间的转换,它可以将基类指针或引用转换为派生类指针或引用。如果进行非法的类型转换,动态类型转换会返回一个空指针。

例如:

class Base {};
class Derived : public Base {};
Base* base = new Derived;
Derived* derived = dynamic_cast<Derived*>(base);
  1. 重新解释类型转换

重新解释类型转换可以将一个对象的二进制表示重新解释为另一种类型的对象,这种转换通常用于底层编程和特殊的系统级程序中。

例如:

int a = 100;
float b = reinterpret_cast<float&>(a);
  1. const_cast转换

const_cast转换可以将const限定符添加或移除,以便在需要更改底层值时使用,但要注意的是,const_cast转换可能会导致未定义行为。

例如:

const int a = 100;
int& b = const_cast<int&>(a);

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/723461.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

微信支付(一):小程序支付(go+gin+内网穿透)

一、前置条件 &#xff08;1&#xff09;go语言&#xff0c;1.18 &#xff08;2&#xff09;Gin、第三方依赖包&#xff1a;gopay【github.com/go-pay/gopay/alipay】https://github.com/go-pay/gopay/blob/main/doc/wechat_v3.md &#xff08;3&#xff09;微信支付相关信息…

Ubuntu安装:显卡驱动、CUDA、Anaconda

Ubuntu安装&#xff1a;显卡驱动、CUDA、Anaconda 摘要1.安装NVIDIA显卡驱动2.安装CUDA3.安装Anaconda Windows环境安装CUDA和Pytorch见&#xff1a;Pytorch入门&#xff1a;3.安装 环境&#xff1a;x86_64 Linux ubuntu18 4.150.0-20-generic 摘要 本篇博客对Ubuntu系统安装…

#消防知识#自动灭火系统是什么?

自动灭火系统是指能够在发生火灾时自动检测、控制和扑灭火灾的系统&#xff0c;包括自动喷水灭火系统、气体灭火系统、干粉灭火系统、气溶胶灭火系统等。不同的自动灭火系统有不同的组成部件、工作原理和适用范围&#xff0c;以下是一些简要的介绍&#xff1a;• 自动喷水灭火系…

汽车远程升级(OTA)定义与技术体系

1.汽车OTA定义 1.1. OTA概述 OTA&#xff08;Over-the-air technology&#xff09;是一种通过无线方式而不是使用电缆或其他本地连接进行数据传输的远程升级。能够实现对现有性能/功能的优化、新功能推送等。OTA技术最早应用于PC&#xff0c;而后在手机上普及&#xff0c;终结…

Go语言程序设计(二)常量、变量、布尔类型与运算符

一、常量、变量与命名规则 常量使用关键字const声明&#xff1b;变量可以使用关键字var声明&#xff0c;也可以使用快捷变量声明语法。Go语言可以自动推断出所声明变量的类型&#xff0c;但是如果需要显式指定其类型也是合法的&#xff0c;比如声明一种与Go语言的常规推断不同的…

途乐证券|沪指缩量跌0.69%,汽车等板块走弱,稀土概念逆市活跃

6日早盘&#xff0c;三大股指股指盘中震动回落&#xff0c;科创50指数逆市上扬&#xff1b;两市半日成交超5000亿元&#xff0c;北向资金小幅净流出。 到午间收盘&#xff0c;沪指跌0.53%报3205.97点&#xff0c;深成指跌0.39%&#xff0c;创业板指跌0.61%&#xff0c;科创50指…

新版 Alist + RaiDrive 挂载阿里云盘 Open 到本地,实现网盘本地化

新版 Alist RaiDrive 挂载阿里云盘 Open 到本地&#xff0c;实现网盘本地化 1. 下载 Alist 和 RaiDrive2. 配置 Alist3. 填写挂载路径和刷新令牌4. 获取刷新令牌5. 使用 RaiDrive 挂载 1. 下载 Alist 和 RaiDrive 下载地址&#xff1a;Alist RaiDrive 安装 提取码: qu38 Al…

XXX SAP系统中支持XX动力替代件功能(投稿数字化月报三)

XXX集团、XX动力、XXX汽车IT组成替代件开发小组&#xff0c;快速高效完成XX动力替代件业务需求。提供从XX动力的PLM系统中开发新增含有替代件功能的BOM物料清单、在XXX汽车SAP系统中启用替代件功能、再到现场替换件业务执行的全套解决方案。 在BOM上体现出物料的替换关系&#…

汽车电子—制作DBC文件

文章目录 一、前期准备二、新建DBC文件三、添加报文&#xff08;Msg&#xff09;四、添加信号4.1 大小端模式4.2 创建数值表4.3 添加信号 五、关联信号和报文六、设置报文发送类型和周期七、编辑通信矩阵 一、前期准备 首先需要安装制作DBC文件的软件&#xff0c;这里使用的是…

计算机网络概述(二)

计算机网络的定义 计算机网络并没有一个统一的定义&#xff0c;不同阶段是有不同的定义。 最简单的定义&#xff1a;计算机网络是一些互联的&#xff0c;自治的计算机集合。互联&#xff1a;指计算机之间可以通过有线或无线的方式进行数据通信&#xff1b;自治指的是独…

MySQL_01删除主键索引

文章目录 添加主键索引删除主键索引 添加主键索引 alter table 表名 add primary key(字段名)删除主键索引 -- 如果这个主键是自增的&#xff0c;先取消自增长 alter table 表名 modify 字段 int; alter table 表名 drop primary key;

消息队列 原理剖析

什么是消息队列&#xff1f; ​​消息队列是一种用来存储消息的队列。 消息队列能用来做什么&#xff1f; 1、消息或任务的延迟处理。 2、在复杂的业务场景下给系统减压。 3、提示用户体验感&#xff0c;增强用户体验。 4、敏感操作高安全环境处理。 场景举例1&#xff1a…

途乐证券|股票低开好还是高开好?股票低开高走再回落什么意思?

对于一向不涨的股票&#xff0c;出资者常常感到困惑和不安。那么一向不涨的股票要留吗&#xff1f;什么股票更简单上涨&#xff1f;为我们预备了相关内容&#xff0c;以供参阅。 一向不涨的股票要留吗&#xff1f; 一向不涨的股票要不要留没有一个绝对的答案&#xff0c;出资者…

Vue2.0-3.0 入门到实战 - 2 初始及插件安装

1 Vue 指令 v- 前缀的 特殊标签属性 1 v-html"表达式" 可以解析 文本html 类似 innerHtml 2 v-show 与 v-if v-show"表达式" true 表示 显示 false 标识隐藏 v-if"表达式" true 表示 显示 false 标识隐藏 区别 当v-show 的值…

青岛大学_王卓老师【数据结构与算法】Week04_05_双向链表的删除_学习笔记

本文是个人学习笔记&#xff0c;素材来自青岛大学王卓老师的教学视频。 一方面用于学习记录与分享&#xff0c;另一方面是想让更多的人看到这么好的《数据结构与算法》的学习视频。 如有侵权&#xff0c;请留言作删文处理。 课程视频链接&#xff1a; 数据结构与算法基础–…

【CMake】构建类型详细解读

1. CMAKE_BUILD_TYPE官方资料 CMake可以配置构建类型&#xff0c;例如&#xff1a;Debug、Release等&#xff0c;控制生成构建系统使用的配置变量 是 CMAKE_BUILD_TYPE 。该变量默认为空&#xff0c;CMake识别的值为:Debug&#xff1a;用于在没有优化的情况下&#xff0c;使用带…

音频格式怎么转换成WAV?分享这三个WAV转换器!

随着数字时代的进步与发展&#xff0c;音频格式也变得越来越多样化。人们为了满足自己的需求&#xff0c;开始使用各种音频格式来存储和播放音乐。然而&#xff0c;不同的音频格式和不同的播放器之间常常存在兼容性问题&#xff0c;这就需要我们进行音频格式转换&#xff0c;以…

Spark SQL、DataFrame、DataSet是什么

在很多情况下&#xff0c;开发人员并不了解Scala语言&#xff0c;也不了解Spark常用的API&#xff0c;但又非常想要使用Spark框架提供的强大的数据分析能力。Spark的开发工程师们考虑到了这个问题&#xff0c;于是利用SQL语言的语法简洁、学习门槛低以及在编程语言中普及程度和…

开放式耳机推荐,盘点几款好用的开放式耳机

一款好的开放式蓝牙耳机不仅可以让我们缓解疲劳&#xff0c;还能更有动力&#xff0c;特别是音质的表现&#xff0c;如果一款开放式耳机的音质表现不好&#xff0c;那这款耳机也就没有多大意义了&#xff0c;还有就是佩戴舒适性&#xff0c;所以选择一款好的开放式蓝牙耳机也很…

vs2015调试时无法显示QT变量值

问题描述&#xff1a; vs2015调试时无法显示 QT变量值&#xff0c;只能显示地址&#xff0c;导致想要查看变量值的时候&#xff0c;只能想办法打印出来&#xff0c;非常麻烦。如下图&#xff1a; 问题解决&#xff1a; 调试 - 选项 - 调试 - 常规 - 去掉 使用本机兼容性模式&am…