【C++学习笔记】C++如何规范C语言中的类型转换

C++的类型转换

  • 1 C语言中类型转换的缺陷
  • 2 为什么C++要规范C的类型转换
  • 3 C++强制类型转换
    • 3.1 static_cast
    • 3.2 reinterpret_cast
    • 3.3 const_cast
    • 3.4 dynamic_cast

1 C语言中类型转换的缺陷

在C语言中,如果赋值运算符左右两侧类型不同,或者形参与实参类型不匹配,或者返回值类型与接收返回值类型不一致时,就需要发生类型转化。
C语言中总共有两种形式的类型转换:隐式类型转换和显式类型转换。

  1. 隐式类型转化:编译器在编译阶段自动进行,能转就转,不能转就编译失败。隐式类型转化仅支持相关类型的转换。比如double转int

  2. 显式类型转化:需要用户自己处理的转换,比如不相关类型的转换。
    比如地址转int

int main()
{double d = 1.5;// 隐式类型转换int i = d;cout << d << " " << i << endl;//1.5 1int* p = &i;// 显示的强制类型转换int address = (int)p;cout << p << " " << address << endl;return 0;
}

缺陷: 转换的可视性比较差,所有的转换形式都是以一种相同形式书写,难以跟踪错误的转换

2 为什么C++要规范C的类型转换

C风格的转换格式很简单,但是有不少缺点的:

  1. 隐式类型转化有些情况下可能会出问题:比如数据精度丢失
  2. 显式类型转换将所有情况混合在一起,代码不够清晰

因此C++提出了自己的类型转化风格,注意因为C++要兼容C语言,所以C++中还可以使用C语言的转化风格。

3 C++强制类型转换

标准C++为了加强类型转换的可视性,引入了四种命名的强制类型转换操作符:

static_cast
reinterpret_cast
const_cast
dynamic_cast

3.1 static_cast

static_cast用于非多态类型的转换(静态转换),编译器隐式执行的任何类型转换都可用static_cast,但它不能用于两个不相关的类型进行转换

示例1:两个相关类型的转换

int main()
{double d = 1.5;int i = static_cast<int>(d);cout << d << " " << i << endl;//1.5 1return 0;
}

示例2:两个不相关类型不能使用static_cast进行转换

int main()
{int i = 10;int* p = &i;//int j = static_cast<int>(p);//error,不能这样使用,int和int*是不相关类型int j = (int)p;//C语言方式可以直接转return 0;
}

3.2 reinterpret_cast

reinterpret_cast操作符通常为操作数的位模式提供较低层次的重新解释,用于将一种类型转换为另一种不同的类型

reinterpret_cast可以支持不相关类型的转换
示例1:不相干类型的转换

int main()
{int i = 10;int* p = &i;int j = reinterpret_cast<int>(p);cout << "j=" << j << endl;cout << "p=" << p << endl;return 0;
}

3.3 const_cast

const_cast最常用的用途就是删除变量的const属性,方便赋值

int main()
{const int a = 2;int* p = const_cast<int*>(&a);*p = 3;cout << "a = " << a << endl;//2//注意:这里a其实被修改为3了,但是由于编译器优化的原因//会在预编译的时候之后把这里a替换为2,类似于宏的直接替换cout << "*p = " << *p << endl;//3return 0;
}

这里的a的值其实已经被替换为3了,但是由于a是一个常量,编译器优化的原因,会在预编译的时候把cout那行的a直接替换会2,类似于宏的直接替换。
在这里插入图片描述
可以打开监视窗口查看a的实际的值,确实被修改为3了
在这里插入图片描述
如果想要取消编译器的优化的话,可以加上volatile关键字

int main()
{volatile const int a = 2;int* p = const_cast<int*>(&a);*p = 3;cout << "a = " << a << endl;//3cout << "*p = " << *p << endl;//3return 0;
}

在这里插入图片描述

3.4 dynamic_cast

dynamic_cast用于将一个父类对象的指针/引用转换为子类对象的指针或引用(动态转换)

向上转型:子类对象/指针/引用->父类对象/指针/引用(不需要转换,赋值兼容规则)

这里要处理的是,向下转型:父类对象指针/引用->子类指针/引用(用dynamic_cast转型是安全的)

注意:

  1. dynamic_cast只能用于父类含有虚函数的类
  2. dynamic_cast会先检查是否能转换成功,能成功则转换,不能则返回0

示例1:

class A
{
public:virtual void f(){}
};
class B :public A
{
};
void fun(A* pa)
{//父类的指针转回子类,且父类的指针指向的还是A对象,这时如果强转成B*,是不安全的。B* pb1 = (B*)pa;//C语言方式可以直接转,但是存在安全问题B* pb2 = dynamic_cast<B*>(pa);//这里C++方式不能这样转。返回0cout << "pb1:" << pb1 << endl;cout << "pb2:" << pb2 << endl;
}
int main()
{A a;B b;fun(&a);return 0;
}

在这里插入图片描述
在这里插入图片描述
示例2:

using namespace std;
class A
{
public:virtual void f(){}
};
class B :public A
{
};
void fun(A* pa)
{//父类的指针转回子类,但父类的指针指向是B对象,这时如果强转成B*,是安全的。B* pb1 = (B*)pa;B* pb2 = dynamic_cast<B*>(pa);cout << "pb1:" << pb1 << endl;cout << "pb2:" << pb2 << endl;
}
int main()
{A a;B b;fun(&b);return 0;
}

在这里插入图片描述
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【unity小技巧】委托(Delegate)的基础使用和介绍

文章目录 一、前言1. 什么是委托&#xff1f;2. 使用委托的优点 二、举例说明1. 例12. 例2 三、案例四、泛型委托Action和Func1. Action委托2. Func委托 五、参考六、完结 一、前言 1. 什么是委托&#xff1f; 在Unity中&#xff0c;委托&#xff08;Delegate&#xff09;是一…

【分布式】 ELK 企业级日志分析系统 二

目录 一、FilebeatELK 部署1.1 环境部署 二、grok 正则捕获插件mutate 数据修改插件multiline 多行合并插件date 时间处理插件 一、FilebeatELK 部署 1.1 环境部署 Node1节点&#xff08;2C/4G&#xff09;&#xff1a;node1/192.168.137.101 Elasticsearch Node2节点&…

【Distributed】分布式ELK日志文件分析系统(二)

文章目录 一、FilebeatELK 部署1. 环境部署2. 在 Filebeat 节点上操作2.1 安装 Filebeat2.2 设置 filebeat 的主配置文件 3. 在 Apache 节点上操作3.1 在 Logstash 组件所在节点上新建一个 Logstash 配置文件 3. 启动3.1 在Logstash 组件所在节点启动3.2 在 Filebeat 节点 启动…

git报错:remote: Access denied (URL 403)

git报错&#xff1a;remote: Access denied fatal: unable to access ‘ https:/ /gitee. cohe requested URL 403 大概的原因&#xff0c;是之前更改了 可能因为我之前在git bash中配过ssh&#xff0c;系统已经将指向git的用户设置了别的位置&#xff0c;所以…

基础篇--单片机简介

单片机简介 视频教程 单片机是什么 单片机&#xff1a;Single-Chip Microcomputer 单片微型计算机&#xff0c;是一种集成电路芯片 单片机有什么用&#xff1f; 单片机发展历程 单片机发展超势 CISC Vs RISC CISC和RISC举例 https://wenku.baidu.com/view/b074b0ed998fcc22b…

使用均值漂移来量化带宽分类数据

均值漂移概念 均值漂移的基本概念&#xff1a;沿着密度上升方向寻找聚簇点&#xff0c;其计算过程如下&#xff1a; 1 均值漂移算法首先找到一个中心点center&#xff08;随机选择&#xff09;&#xff0c;然后根据半径划分一个范围 把这个范围内的点输入簇x的标记个数加1 2 在…

【JavaEE】JVM的组成及类加载过程

博主简介&#xff1a;想进大厂的打工人博主主页&#xff1a;xyk:所属专栏: JavaEE初阶 本文我们主要讲解一下面试中常见的问题&#xff0c;如果想深入了解&#xff0c;请看一下《Java虚拟机规范》这本书 目录 文章目录 一、JVM简介 二、JVM整体组成 2.1 运行时数据区组成 2.2…

ELK日志记录——Kibana组件——grok 正则捕获插件

grok 正则捕获插件 grok 使用文本片段切分的方式来切分日志事件 内置正则表达式调用 %{SYNTAX:SEMANTIC} ●SYNTAX代表匹配值的类型&#xff0c;例如&#xff0c;0.11可以NUMBER类型所匹配&#xff0c;10.222.22.25可以使用IP匹配。 ●SEMANTIC表示存储该值的一个变量声明&…

生产环境 kafka 平滑迁移之旅

文章目录 背景分析测试环境验证现实很残酷两种抉择-----leader分区切换方案选择实施步骤手工副本集增加步骤手工leader分区切换步骤 总结 背景 线上kafka集群&#xff0c;3台机器&#xff0c;3个broker&#xff1b;其中某台机器因为硬件故障&#xff0c;需要停机维修&#xff…

表的增删改查

1、创建表 mysql> create table employee ( -> id int(1) comment 员工编号, -> name varchar(6) comment 员工名字, -> gender varchar(2) comment 员工性别, -> salary int (4) comment 员工薪资); Query OK, 0 rows affected (0.01 sec) 2、…

解析三防平板在工业自动化的应用价值

三防平板作为一种具有出色性能和特殊设计的电子设备&#xff0c;为工业自动化领域带来了巨大的应用价值。采用英特尔凌动四核处理器&#xff0c;三防平板具备先进的技术与处理能力。同时配备Window 10操作系统&#xff0c;这款三防平板能够轻松执行多种任务指令。此外&#xff…

支持向量机推导之r||w||=1的限制转化

支持向量机推导之r||w||1的限制转化 很多同学肯定是学过支持向量机的&#xff0c;也可能大致的理解了支持向量机这个算法&#xff0c;我想大部分人在学习这个算法的时候&#xff0c;对于推导过程有一步应该是不太理解。 我先简要介绍一下SVM,SVM的核心思想在于找到一个多维空间…