c++ 数据类型转换: static_cast dynamic_cast reinterpret_cast const_cast

c++ 数据类型转换: static_cast dynamic_cast reinterpret_cast const_cast

【版权声明】转载请注明出处 http://www.cnblogs.com/TenosDoIt/p/3175217.html

【目录】

引言

static_cast 定义

dynamic_cast 定义

举例:下行转换(把基类的指针或引用转换成子类表示)

举例:上行转换(把子类的指针或引用转换成基类表示)

举例: static_cast 用于基本类型之间、基本类型指针和空指针间的转换

reinterpret_cast 定义

举例:reinterpret_cast用法

const_cast 定义

举例:const_cast用法

总结


 

c语言中我们经常使用类似于 int a =(int)3.14等这种强制类型转换

标准c++的类型转换符:static_cast 、dynamic_cast、 reindivter_cast、 const_cast, 以下分别介绍他们的用法以及举例说明

以下代码编译运行环境:codeblock with gcc in win7(x64)

【1】static_cast 
用法:static_cast < type-id > ( exdivssion ) 

该运算符把exdivssion转换为type-id类型,但没有运行时类型检查来保证转换的安全性。它主要有如下几种用法:

①用于类层次结构中基类和子类之间指针或引用的转换。

  进行上行转换(把子类的指针或引用转换成基类表示)是安全的;

  进行下行转换(把基类指针或引用转换成子类表示)时,由于没有动态类型检查,所以是不安全的。

②用于基本数据类型之间的转换,如把int转换成char,把int转换成enum。这种转换的安全性也要开发人员来保证。

③把空指针转换成目标类型的空指针。

④把任何类型的表达式转换成void类型。

注意:static_cast 不能转换掉exdivssion的const、volitale、或者__unaligned属性。

msdn官方解释:http://msdn.microsoft.com/en-us/library/c36yw7x9(v=vs.80).aspx

【2】dynamic_cast

用法:dynamic_cast < type-id > ( exdivssion )

该运算符把exdivssion转换成type-id类型的对象。Type-id必须是类的指针、类的引用或者void *;

如果type-id是类指针类型,那么exdivssion也必须是一个指针,如果type-id是一个引用,那么exdivssion也必须是一个引用。

dynamic_cast主要用于类层次间的上行转换和下行转换,还可以用于类之间的交叉转换。

在类层次间进行上行转换时,dynamic_cast和static_cast 的效果是一样的;

在进行下行转换时,dynamic_cast具有类型检查的功能,比static_cast 更安全。

msdn官方解释:http://msdn.microsoft.com/en-us/library/cby9kycs(v=vs.80).aspx

 

举例:下行转换(把基类的指针或引用转换成子类表示)

需要注意的是如果基类中不含虚函数,dynamic_cast 下行转换编译会出错

复制代码
 1 #include<iostream>2 using namespace std;3 4 class father5 {6 public:7     void fun1()8     {9         cout<<"this is father fun1 call\n";
10     }
11     virtual void fun()
12     {
13         cout<<"this is father fun call\n";
14     }
15 };
16 
17 class son: public father
18 {
19 public:
20     void fun2()
21     {
22         cout<<"this is son fun2 call\n";
23     }
24     void fun()
25     {
26         cout<<"this is the son fun call\n";
27     }
28     int k;
29 };
30 
31 int main()
32 {
33     father *pf, f;
34     son *ps, s;
35 
36     pf = &f;// 基类的指针指向基类对象
37     ps = static_cast<son *>(pf);//这种转换是不安全的,行为是不确定的
38     if(ps != NULL)
39     {
40         ps->fun(); //在本文编译环境下,执行父类的fun
41         //本文编译环境下,一下语句可以执行
42         ps->fun2();
43         ps->k = 1;
44     }
45     ps = dynamic_cast<son *>(pf);//转换后ps = NULL
46     if(ps == NULL)
47         cout<<"dynamic_cast: ps = NULL\n";
48     cout<<"-----------------------------------------------------------------\n";
49     pf = &s; //基类指针开始指向子类对象
50     //此时,两种转换都是安全的
51     ps = static_cast<son *>(pf);
52     if(ps != NULL)
53     {
54         ps->fun();
55         ps->fun2();
56         ps->k = 1;
57     }
58     ps = dynamic_cast<son *>(pf);//转换后ps = NULL
59     if(ps != NULL)
60     {
61         ps->fun();
62         ps->fun2();
63         ps->k = 2;
64     }
65 }
复制代码

结果:

举例:上行转换(把子类的指针或引用转换成基类表示)

复制代码
 1 //类定义同上2 int main()3 {4     father *pf, f;5     son *ps, s;6 7     ps = &s;// 子类的指针指向子类对象8     //此时两种转换都是安全的9     pf = static_cast<father *>(ps);
10     if(pf != NULL)
11     {
12         pf->fun();
13     }
14     pf = dynamic_cast<father *>(ps);
15     if(pf != NULL)
16     {
17         pf->fun();
18     }
19 
20 }
复制代码

举例: static_cast 用于基本类型之间、基本类型指针和空指针间的转换(不能用于基本类型指针之间转换)。

注意:基本类型由于表示数值范围的不同,因此需要用户保证转换的安全。另外dynamic_cast不能用于此类转换

复制代码
 1 int main()2 {3     //基本类型间的转换,需要用户保证安全4     int a = 1000;5     char c = static_cast<char>(a);//不安全,1000超过了char的表示范围6     cout<<c<<endl;//输出空7     a = 49;8     c = static_cast<char>(a);//安全,输出字符‘1’9     cout<<c<<endl;
10     //c = dynamic_cast<char>(a); 错误
11     cout<<"-----------------------------------------------------------------\n";
12     //void *和基本类型指针的转换,需要用户保证转换安全
13     a = 49;
14     void *pv;
15     pv = &a;
16     int *pi = static_cast<int *>(pv);//void * 转换为int *
17     cout<<*pi<<endl; //输出49
18     //pi = dynamic_cast<int *>(pv); 错误
19     char *pc = static_cast<char *>(pv);//void *转char*
20     cout<<*pc<<endl;//输出字符‘1’
21     void *pv2 = static_cast<void *>(pc);// char * 转void *
22     cout<<*((char *)pv2)<<endl;输出字符‘1’
23 }
复制代码

 

【3】reinterpret_cast

用法:reinterpret_cast<type-id> (exdivssion)

reinterpret_cast运算符是用来处理无关类型之间的转换;它会产生一个新的值,这个值会有与原始参数(expressoin)有完全相同的比特位。按照reinterpret的字面意思“重新解释”,即对数据的比特位重新解释。

IBM的C++指南 里明确告诉了我们reinterpret_cast可以,或者说应该在什么地方用来作为转换运算符:

  • 从指针类型到一个足够大的整数类型
  • 从整数类型或者枚举类型到指针类型
  • 从一个指向函数的指针到另一个不同类型的指向函数的指针
  • 从一个指向对象的指针到另一个不同类型的指向对象的指针
  • 从一个指向类函数成员的指针到另一个指向不同类型的函数成员的指针
  • 从一个指向类数据成员的指针到另一个指向不同类型的数据成员的指针

总结来说:reinterpret_cast用在任意指针(或引用)类型之间的转换;以及指针与足够大的整数类型之间的转换;从整数类型(包括枚举类型)到指针类型,无视大小。

注意:static_cast 不能转换掉exdivssion的const、volitale、或者__unaligned属性。

msdn官方解释:http://msdn.microsoft.com/en-us/library/e0w9f63b(v=vs.80).aspx

举例:reinterpret_cast用法

复制代码
 1 int main()2 {3    int a = 49;4    int *pi = &a;5    char *pc = reinterpret_cast<char*>(pi);//int * 到char *,用户自己安全6    cout<<*pc<<endl; //输出字符"1"7    unsigned long b = reinterpret_cast<unsigned long>(pc);//char * 转 unsigned long8    cout<<b<<endl;//输出pc指向地址(即a的地址)对应的整数9    int *pi2 = reinterpret_cast<int *>(b);//unsigned long 转 int*
10    cout<<*pi2<<endl; //输出49
11 }
复制代码

【4】const_cast 

用法:const_cast<type-id> (exdivssion)

该运算符用来修改类型的const、volatile、__unaligned属性。除了const 、volatile、__unaligned修饰之外, type_id和exdivssion的类型是一样的。

常量指针被转化成非常量指针,并且仍然指向原来的对象;

常量引用被转换成非常量引用,并且仍然指向原来的对象;常量对象被转换成非常量对象。

msdn官方解释:http://msdn.microsoft.com/en-us/library/bz6at95h(v=vs.80).aspx

举例:const_cast用法

复制代码
1 int main()
2 {
3    const int a = 100;
4    int *b = const_cast<int *>(&a);//const int * 转int *
5    cout<<*b<<endl; //输出100
6    cout<<&a<<" "<<b<<endl; //两者值相同,表明b指向a的地址,只是const属性变了
7 }
复制代码


总结:

类指针或引用的上行转换static_cast 和 dynamic_cast 都可以

类指针或引用的下行转换用dynamic_cast并且判断转换后是否为空

基本数据类型之间的转换用static_cast, 但是由于数值范围的不同,需要用户保证转换的安全性

不同类型之间的指针或引用的转换用reinterpret_cast,它的本质是对指向内存的比特位的重解释

消除数据的const、volatile、__unaligned属性,用const_cast

【版权声明】转载请注明出处 http://www.cnblogs.com/TenosDoIt/p/3175217.html

转载于:https://www.cnblogs.com/glllvwcc/p/5051393.html

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

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

相关文章

C语言试题二十八之编写函数function功能是:从字符中删除指定的字符,同一字母的大、小写按不同字符处理。

📃个人主页:个人主页 🔥系列专栏:C语言试题200例目录 💬推荐一款刷算法、笔试、面经、拿大公司offer神器 👉 点击跳转进入网站 ✅作者简介:大家好,我是码莎拉蒂,CSDN博客专家(全站排名Top 50),阿里云博客专家、51CTO博客专家、华为云享专家 1、题目 编写函数f…

日用有余!国产中科方德桌面操作系统初体验

国产IT圈里最受关注的话题&#xff0c;除了芯片想必就是操作系统了。但真说起国产操作系统&#xff0c;大家是既熟悉又陌生&#xff0c;听说过的多而真正使用过的少。而伴随产业发展&#xff0c;市面上也涌现出众多国产操作软件&#xff0c;这些系统是否好用&#xff1f;能否满…

面试经验总结

8 transient是干嘛的 Java的serialization提供了一种持久化对象实例的机制。当持久化对象时&#xff0c;可能有一个特殊的对象数据成员&#xff0c;我们不想用 serialization机制来保存它。为了在一个特定对象的一个域上关闭serialization&#xff0c;可以在这个域前加上关键字…

【GIS风暴】ArcGIS栅格重采样(Resample)方法详解

Contents 1. 最邻近法(Nearest Neighbor)2. 双线性内插法(Bilinear Interpolation)3. 三次卷积法(Cubic Convolution)4. ArcGIS重采样工具(Resample)栅格/影像数据进行配准或纠正、投影等几何变换后,像元中心位置通常会发生变化,其在输入栅格中的位置不一定是整数的行…

Unhandled event loop exception PermGen space

原来一直用eclipse3.5&#xff0c;最近尝试升级到3.7和4.2&#xff0c;但不管是3.7还是4.2项目编译过程中总提示“Unhandled event loop exception PermGen space”要求退出workspace&#xff0c;与原来3.5版本比较了一下eclipse.ini参数设置发现没有差别&#xff0c;怀疑是公司…

C# RichTextBox 做简单的HTML代码编辑器 ---------利用WinApi修正左侧显示行号 误差

说明&#xff1a;通过WinApi可以准确定准滚动位置。 //行号 生成显示 这里rtbLineNum用的 RichTextBox&#xff0c;也可以用其它private void ShowLineNum(){rtbLineNum.Text "";//计算行高&#xff0c;行数int linesLength 0;var pFirst tbEditor.GetPositionFr…

Angular - - angular.element

angular.element 将DOM元素或者HTML字符串一包装成一个jQuery元素。 格式&#xff1a;angular.element(element); element&#xff1a;包装成jquery对象的html字符串或者dom元素 jqLite提供的方法&#xff1a; addClass()after()append()attr()bind() – 不支持命名空间,选择器…

六、文章详情显示及点赞实现《iVX低代码/无代码个人博客制作》

注&#xff1a;iVX也有免费直播课《第八期直播课》 一、文章详情实现 上一节我们已经完成了首页的内容显示&#xff0c;那么此时我们完成点击后跳转到详情页内容。 那么此时由于我们需要跳转到详情页需要对应的数据ID&#xff0c;那么此时还需要给首页的文章数据对象数组一个…

centos格式化xfs文件系统格式并设置自动启动挂载磁盘

文章目录 说明操作步骤 说明 非全方位资料&#xff0c;学习实践而来&#xff0c;欢迎参考学习 操作步骤 要将 /dev/sdb1 分区快速格式化为 XFS 文件系统并设置开机自动挂载&#xff0c;可以按照以下步骤进行操作&#xff1a; 查看已连接的硬盘列表&#xff0c;主要是设备名称…

System.CommandLine选项Option

前一篇简单看了一下CommandLine命令的使用&#xff0c;其实在一个命令行工具中&#xff0c;还有一个重要的点&#xff0c;那就是选项——Option&#xff0c;选项是为命提供参数&#xff0c;就好像C#中方法&#xff0c;Command就像方法&#xff0c;Option就像方法的参数&#xf…

长尾关键词如何优化

长尾关键词流量占据全站流量的80%&#xff0c;这是根据御梵景观后台数据得出来的结论&#xff0c;千万不要以为泛关键词给网站带来的流量大&#xff0c;打个比方花园设计一天带100个 流量&#xff0c;但是花园设计案例带10个&#xff0c;花园设计效果图带10个&#xff0c;花园设…

【ArcGIS风暴】ArcGIS10.6栅格计算器(Raster Calculator)用法详解

扩展阅读: 【ArcGIS风暴】ArcGIS 10.2栅格计算器实用公式大全(经典珍藏版) 【ArcGIS风暴】栅格计算器(Raster Calculator)运算出现错误问题及解决方案汇总 文章目录 1. 栅格计算器简介2. 栅格计算器用法3. 简单算术运算4. 数学函数运算5. 空间分析函数运算1. 栅格计算器简…

C语言试题二十九之编写函数int function(int lim,int aa[max])求出小于或等于lim的所有素数并放在aa数组中,该函数返回所求的素数的个数。

📃个人主页:个人主页 🔥系列专栏:C语言试题200例目录 💬推荐一款刷算法、笔试、面经、拿大公司offer神器 👉 点击跳转进入网站 ✅作者简介:大家好,我是码莎拉蒂,CSDN博客专家(全站排名Top 50),阿里云博客专家、51CTO博客专家、华为云享专家 1、题目 编写函数i…

三、登录页制作《iVX低代码/无代码个人博客制作》

注&#xff1a;iVX也有免费直播课《第八期直播课》 一、登录页实现 本节需要做的登录页如下&#xff1a; 该页面我们复习可以的值&#xff0c;首先设置整个页面页面的垂直和水平对其为居中&#xff0c;随后一个容器包裹对应的登录区域&#xff0c;此时我们创建一个页面命名为…

Android ContentProvider支持跨进程数据共享与互斥、同步 杂谈

在开发中&#xff0c;假如&#xff0c;A、B进程有部分信息需要同步&#xff0c;这个时候怎么处理呢&#xff1f;设想这么一个场景&#xff0c;有个业务复杂的Activity非常占用内存&#xff0c;并引发OOM&#xff0c;所以&#xff0c;想要把这个Activity放到单独进程&#xff0c…

【C#控件详解】对话框类控件(打开文件,保存文件,选择字体和颜色)

在实际应用中,我们会用到各种各样的对话框,如打开文件,保存文件,选择字体和颜色等等。本文详细讲解C#中的颜色对话框、打开文件对话框、字体对话框、浏览文件夹对话框和保存文件对话框。 文章目录 1. ColorDialog对话框2. FolderBrowserDialog对话框3. FontDialog对话框4. …

动物界的再生一个故事

猪月薪5千&#xff0c;打算用20万建一个窝&#xff0c;老虎不允许&#xff0c;说私自建就是违章建筑&#xff0c;只允许向狼买。 狼是搞工程的&#xff0c;先用20万贿赂老虎取得开发权&#xff0c;再用50万元向老虎买这块地&#xff0c; 花10万元把猪圈盖好&#xff0c;向猪要价…

C语言试题三十之请编写函数function对长度位7个字符的字符串,除首尾字符外,将其余5个字符按ascii码降序排列。

📃个人主页:个人主页 🔥系列专栏:C语言试题200例目录 💬推荐一款刷算法、笔试、面经、拿大公司offer神器 👉 点击跳转进入网站 ✅作者简介:大家好,我是码莎拉蒂,CSDN博客专家(全站排名Top 50),阿里云博客专家、51CTO博客专家、华为云享专家 1、题目 请编写函数…

基于.NetCore开发博客项目 StarBlog - (11) 实现访问统计

系列文章基于.NetCore开发博客项目 StarBlog - (1) 为什么需要自己写一个博客&#xff1f;基于.NetCore开发博客项目 StarBlog - (2) 环境准备和创建项目基于.NetCore开发博客项目 StarBlog - (3) 模型设计基于.NetCore开发博客项目 StarBlog - (4) markdown博客批量导入基于.N…

【SPSS统计分析】SPSS19.0简体中文版安装教程(附SPSS19.0简体中文版下载)

spss19.0中文版是一款专业数据统计软件,受到各种社会学科的研究生、研究员的欢迎。软件能够对信息的采集、处理、分析进行全面评估和预测。spss19.0中文版新增加了广义线性混合模型、自动线性模型、一个统计网页入口portal和直复营销direct marketing功能等。另外,IBM 针对SP…