C++学习之路(六):关于C++提供的强制类型转换

C语言中提供了旧式的强制类型转换方法。比如:

int a  =1;

char *p = (char *)&a;

上述将a的地址单元强制转换为char类型的指针。这里暂且不说上述转换结果是否合理,但上述这样的强制类型转换,如果转换过程出现问题,对于问题的追踪与排查也比较困难。

对于C++而言,提供了较为安全的强制类型转换方法,下面进行简单介绍。

一、static_cast

对于任何具有明确定义的类型转换,只要不包含底层const,都可以用static_cast。

主要可以有以下几种转换:

(1)用于基本数据类型之间的转换,如把int转换为char,把int转换为enum,但这里的转换的安全性需要由开发者自己保证;

(2)把空指针转换成目标类型的指针,这里有点类似旧式的强制类型转换的void*指针转换,但同样,对指针类型的解析,需要由开发者自己保证

(3)把任何类型的表达式类型转换为void类型;

(4)用于类层次结构中父类和子类之间指针和引用的转换。

上面的几点后续遇到了样例再进行补充,这里给一个转换void*指针的样例说明。

代码1:

int a = 1;
char *q = static_cast<char*>(&a);
cout<<*q<<endl;

上述代码不能被编译通过,因为static_cast对于指针的转换,只能接受void*类型,上述&a依然是int型指针,不能通过编译。

代码2:

int a = 1;
char *q = static_cast<char*>((void *)&a);
cout<<*q<<endl;

通过将&a转型为void*指针,完成对类型的强制转换,上述代码结果正常输出。

二、const_cast

在由const关键字定义的变量,是不能在后续被修改的。比如:

  const int a = 1;

  a = 2;

上述编译不通过,因为a不能被进行修改。

这里我们依然先看一个样例:

  

int func(int &a)
{
    return 0;
}

int main(void)
{
    const int a = 1;
    func(a);
    return 0;
}

上述代码中,a是一个const变量,但在func函数中的形参需要一个int型变量。很显然,编译直接报错,因为实参与形参具有不同的类型。如何解决这个问题?这就需要引入const_cast进行类型转换

const_cast只能改变运算对象的底层const。即对于一个const对象,const_cast可以将其const限定移除。上述代码修改为:

int func(int *a)
{
    return 0;
}

int main(void)
{
    const int a = 1;
    int *p = const_cast<int*>(&a);
    func(p);
}

这里将const的变量a的指针,强制类型转换为非const的指针,在func中传入指针变量,程序即可以成功编译。

这里就有一个疑问:如果可以const_cast将const变量转换为非const变量,是否意味着,可以对const变量进行修改?如果可以,那是不是违背了const关键字的初衷?   这里再看一个样例代码:

int main(void)
{
    const int a = 5;
    const int *p = &a;
    int *q = const_cast<int*>(p);

    cout<<&a<<endl;
    cout<<p<<endl;
    cout<<q<<endl;

    cout<<*q<<endl;
    *q = 6;
    cout<<*p<<endl;
    cout<<a<<endl;
    return 0;
}

a是一个const变量,p是一个const指针指向a,q通过const_cast强制类型转换p得到一个非const指针。

直接贴出程序结果,再进行分析:

结果可以看到,&a,p,q的值都是相同的,证明p和q指针都正确指向了a的地址单元。接下来输出*q,为a的原值5,再对*q进行了修改,输出*p,结果为成功修改后的6。但最后输出a变量,发现a变量依然为原值5。

结论很明显了:对于const变量,仍然不能够修改它本身的值,这是限定符自身的约束。

三、reinterpret_cast

关于reinterpret_cast,感觉更比较贴合旧式的强制类型转换。举个例子:

int a = 1;
char *q = reinterpret_cast<char*>(&a);
cout<<*q<<endl;

上述对于static_cast的使用,需要对&a转换为void*才能够进行,但使用reinterpret_cast则可以直接进行转换。reinterpret_cast本质上依赖于机器。

四、dynamic_cast

关于dynamic_cast,用法比较丰富,会再之后进行讨论。

结论:对于一条强制类型转换的语句,都应该反复斟酌是否能用其他方式来实现相同的目标,就算实在无法避免,也应用尽量限制类型转换值的作用域,并记录对相关类型的所有假定,这样可以减少错误发生的机会。

原文地址:https://www.cnblogs.com/scu-cjx/p/8758512.html

时间: 2024-10-15 06:00:23

C++学习之路(六):关于C++提供的强制类型转换的相关文章

react.js学习之路六

学习react中,我一直认为,总组件里面才有构造函数,但是我才发现我的观点是错误的,构造函数是可以出现在子组件里面的. 今天有一个错误是点击增加/减少input框里面 的数值 我一直在寻找input框里面的数值,也就是value值,我发现我的思维错误的很彻底.react只是view,是不能操作数据的,只能渲染原始数据的变化,换句话说就是我要改变数值,只能改变原始数据里面的值,然后重新渲染到input框里面. 我的原始数据,给了 value:1; 当点击时候,构造函数 add(e){ var nu

Java学习之路(六):集合

集合的由来 数组的长度是固定的,当添加的元素超过了数组的长度,就需要对数组重新定义 java内部给我们提供的集合类,能存储任意对象,长度是可以改变的.随着元素的增加而增加,随着元素的减少而减少 数组和集合的区别 数组既可以存储基本数据类型,又可以存储引用数据类型,基本数据类型存储的是值,引用数据类型存储的是地址值 集合只能存储引用数据类型(对象Object),集合中也可以存储基本数据类型,但是在存储的时候会自动装箱变成对象  eg:int==>Integer 数组长度是固定的,不能自动增长 集合

Java学习之路(六)

1:包及和访问权限 将类放置到一个包当中,需要使用package “包名” 编译时需要使用 -d 参数  该参数的作用是依照包名生成相应的文件夹 一个类的全民应该是  “包名” + “.” + “类名” 包名的命名规范: 要求包名所有的字母都要小写 包名一般情况下,是你的域名倒过来写 一个包中的类访问另一个包中的类的条件 1:先自己打个包 1:访问类导入包名 2:被访问类必须是公共的 在以上条件下 :如果想要一个类想访问另一个类的属性和方法时,他们必须是公共(public)的 public   

我的java学习之路六:java的常用类

一. Number & Math 类方法 下面的表中列出的是 Number & Math 类常用的一些方法: 序号 方法与描述 1 xxxValue()将 Number 对象转换为xxx数据类型的值并返回. 2 compareTo()将number对象与参数比较. 3 equals()判断number对象是否与参数相等. 4 valueOf()返回一个 Number 对象指定的内置数据类型 5 toString()以字符串形式返回值. 6 parseInt()将字符串解析为int类型. 7

android开发学习之路——连连看之游戏逻辑(五)

GameService组件则是整个游戏逻辑实现的核心,而且GameService是一个可以复用的业务逻辑类. (一)定义GameService组件接口 根据前面程序对GameService组件的依赖,程序需要GameService组件包含如下方法.   ·start():初始化游戏状态,开始游戏的方法.     ·Piece[][] getPieces():返回表示游戏状态的Piece[][]数组.     ·boolean hasPieces():判断Pieces[][]数组中是否还剩Piec

C++学习之路,漫长而遥远

一.C/C++语言 如果你的基础很差, 建议不要一开始就学C++语言,从C开始学起,对程序有个初步的认识,循序渐进.C语言的书嘛,先买一本 300 页以内的,把书中的每一个例子都通过键盘敲打进去到 Visual studio里面去,然后单步执行,逐行调试去看各个变量的值.或者自行添加一些printf语句去输出变量的值.这样当你看完一本书后, 你就有编写小程序的感觉了. 记住,千万不要偷懒,不敲进去,自以为聪明, 能看懂, 或者直接从光盘复制.偷懒的代价是会花费更多的时间学习,最后还没有学会,给自

java学习之路之javaSE基础1

<h2>java学习之路之javaSE基础1</h2> <div> ###01.01_计算机基础知识(计算机概述)(了解)* A:什么是计算机?计算机在生活中的应用举例 * 计算机(Computer)全称:电子计算机,俗称电脑.是一种能够按照程序运行,自动.高速处理海量数据的现代化智能电子设备.由硬件和软件所组成,没有安装任何软件的计算机称为裸机.常见的形式有台式计算机.笔记本计算机.大型计算机等. * 应用举例 * 1:科学计算 * 2.数据处理 * 3.自动控制 *

kafka学习之路(二)——提高

kafka学习之路(二)--提高 消息发送流程 因为Kafka内在就是分布式的,一个Kafka集群通常包括多个代理.为了均衡负载,将话题分成多个分区,每个代理存储一或多个分区.多个生产者和消费者能够同时生产和获取消息.     过程: 1.Producer根据指定的partition方法(round-robin.hash等),将消息发布到指定topic的partition里面 2.kafka集群接收到Producer发过来的消息后,将其持久化到硬盘,并保留消息指定时长(可配置),而不关注消息是否

LTE学习之路(9)—— 3GPP TS协议系列总结

规范编号 规范名称 内容 更新时间 射频系列规范 TS 36.101 UE无线发送和接收 描述FDD和TDD E-UTRA UE的最小射频(RF)特性 08-Oct-2010 TS 36.104 BS无线发送与接收 描述E-UTRA BS在成对频谱和非成对频谱的最小RF特性 30-Sep-2010 TS 36.106 FDD直放站无线发送与接收 描述FDD直放站的射频要求和基本测试条件 30-Sep-2010 TS 36.113 BS与直放站的电磁兼容 包含对E-UTRA基站.直放站和补充设备的