C++中强制类型转换
C++强制类型转换
C++中的强制类型转换虽然兼容C语言中的强制类型转换。但是并不建议在C++中使用C语言风格的强制类型转换。C++中的强制类型转换共有4个关键字分别是:static_cast,const_cast,reinterpret_cast,dynamic_cast.
static_cast
用于将一种数据类型转换成另一种数据类型,使用格式如下:
变量1 = static_cast<变量1数据类型>(另外一种数据类型变量或表达式);
例如:
int a = 1;
float b;
b = static_cast<float>(a); //类似于C语言中的b = (float)a;
const_cast
用于去除指针和引用的常量性,不能去除变量的常量性。使用格式如下:
指针或引用1 = const_cast<指针或引用1类型>(带常量性的指针或引用2);
例如:
#include <iostream>
using namespace std;
int main()
{
int a = 10;
const int *p = &a; // 被const修饰,不能使用该指针修改其指向内容的值
int *q;
q = const_cast<int *>(p); // 去除p的常量性给q,如果不去除直接赋值会报错
*q = 20;
cout<<"a的地址为:"<<&a<<" a的值为:"<<a<<endl;
cout<<"*q指向的地址为:"<<q<<" *q的值为:"<<*q<<endl;
}
执行结果如下:
a的地址为:0x61ff14a a的值为:20
*q指向的地址为:0x61ff14a *q的值为:20
为了加深理解,我们再看如下一段代码:
#include <iostream>
using namespace std;
const int & Add5(int &a);
int main()
{
const int a = 10; //a的值不允许修改
int b = 20;
const int *p = &a; //被const修饰,不能使用该指针修改其指向内容的值
int *q;
q = const_cast<int *>(p); //去除p的常量性给q,如果不去除直接赋值会报错
*q = 20;
cout<<"a的地址为:"<<&a<<" a的值为:"<<a<<endl;
cout<<"*q指向的地址为:"<<q<<" *q的值为:"<<*q<<endl;
cout<<"b的地址为:"<<&b<<" b的值为:"<<b<<endl;
int &m = const_cast<int &>(Add5(b)); //去掉函数的const属性,不去掉就赋值给不带const的引用会报错
cout<<"调用加5函数之后"<<endl;
cout<<"引用m指向的地址为:"<<&m<<" 引用m指向的值为:"<<m<<endl;
}
//返回输入值+5,返回的引用不可被修改
const int & Add5(int &a)
{
a+=5;
return a;
}
执行结果如下:
a的地址为0x61ff10 a的值为:10
*q指向的地址为:0x61ff10 *q的值为:20
b的地址为:0x61ff0c b的值为:20
调用加5函数之后
引用m指向的地址为:0x61ff0c 引用m指向的值为:25
上面这段程序有两点说明:
- 对变量a加上了const属性,因此a的值是不会被程序所改变的。即使我们将指向a的指针的const属性去掉重新赋值,也不会改变。但是会出现变量a和指针q指向地址相同,但值不同的现象。
- 对变量b的操作我们可以看出,const_cast不仅仅能去掉指针的const,也能去掉引用的const。不仅仅能去掉变量表达式的const也能去掉函数的const。
最后,在强调一遍。const_cast不能去掉变量的const.这是编程安全的基础。像下面这种操作是错误的。除了const之外,const_cast也能去掉volatile属性,和去掉const一样。
const int a = 10;
int b = const_cast<int>(a); //变量的const属性去不掉,错误
reinterpret_cast
reinterpret_cast这种强制类型转换是一种非常强的强制类型转换,它可以将任意两个无关的指针或引用进行转换。上面的static_cast进行强制类型转换时,会进行编译时的类型安全检查,即你可以将int转成float,将子类引用(指针)转成父类引用(指针),子转父和父转子都可以,但父转子不安全。但是你不能使用static_cast将两个无关的东西进行转换,比如两个无关的类,因为编译器在编译的时候会检查这个转换是否可行,很明显不可行。
ClassB *p = &b;
ClassA *q = static_cast<ClassA &>(p); //如果ClassA和ClassB有关系,编译能通过,否则不通过
但是如果使用的reinterpret_cast强制类型转换,就不会进行静态类型检查直接放行通过。当然如果这两个类如果没有关系,那么在运行的过程就会“跑偏出错”。为了防止在运行的过程中“跑偏”,我们除静态类型转换(static_cast)之外还需要一个动态的类型转换(dynamic_cast).
比较常用的一种reinterpret_cast的用法是,使用其将一个整形转化为一个IO设备的地址。比如我们写一段DSP程序,这个DSP外部数据总线上挂了一个FPGA,这段程序的作用就是读写FPGA中的的数据。下面给出了C风格的设备地址定义和C++风格的设备地址定义。
// C风格的设备地址定义
Uint16 *FpgaAddr0 = (Uint16*)0x200000; //Fpga第0个寄存器地址
//C++风格的设备地址定义
Uint16 *FpgaAddr0 = reinterpret_cast<Uint16 *>0x200000; //Fpga第0个寄存器地址
dynamic_cast
前面我们介绍过了static_cast,从名称上来看,两个一动(dynamic)一静(static)肯定有关系。我们知道static_cast会在编译的过程中进行安全性检查,而dynamic_cast会在运行的过程中进行安全性检查。这两个都带安全性检查可以防止错误的类型转换导致程序跑偏。
dynamic_cast既然是动态安全性检查,那么它肯定只能应用于指针或引用,不能用于内置的数据类型转换(内置的数据类型转换,在编译阶段由static_cast检查即可)。dynamic_cast不但检查两个指针是否属于同一个继承树(static_cast也检查这个),还会检测这种转换是否可行。如果可行就会返回一个新指针,并计算出为处理多继承的需要的必要的偏移量。如果不可行会返回NULL。因此即使我们使用reinterpret_cast强制类型转换骗过编译器编译成功,如果我们在使用前再使用dynamic_cast转换检测一下的话,还是能发现这个错误的转换的。
总结
- static_cast会进行静态的安全性检查,一般用于内置数据类型的转换和通常的类之间的转换。
- const_cast主要是用来去掉指针和引用的const和volatile类型。
- reinterpret_cast用于完全没有关系指针或引用之间的转换,比如字符指针转整形指针。
- dynamic_cast通常用于基类和派生类之间的相互转换。
C++中强制类型转换的更多相关文章
- java中强制类型转换
在Java中强制类型转换分为基本数据类型和引用数据类型两种,这里我们讨论的后者,也就是引用数据类型的强制类型转换. 在Java中由于继承和向上转型,子类可以非常自然地转换成父类,但是父类转换成子类则需 ...
- C语言中强制类型转换总结
C语言中强制类型转换总结 ● 字符型变量的值实质上是一个8位的整数值,因此取值范围一般是-128-127,char型变量也可以加修饰符unsigned,则unsigned char 型变量的取值范围 ...
- c#中的里氏转换和Java中强制类型转换在多态中的应用
在c#中: 注意: 子类并没有继承父类的构造函数,而是会默认调用父类那个无参数的构造函数. 如果一个子类继承了一个父类,那么这个子类除了可以使用自己的成员外,还可以使用从父类那里继承过来的成员.但是父 ...
- javascript中强制类型转换
javascript开发过程中,强制类型转换一般发生在条件判断和==运算符.其他情况,发生的类型转换(与这两种情况也是基本类似,属于万变不离其宗的范畴),暂不讨论. == 双等运算符 考虑代码: a ...
- C++解析(25):关于动态内存分配、虚函数和继承中强制类型转换的疑问
0.目录 1.动态内存分配 1.1 new和malloc的区别 1.2 delete和free的区别 2.虚函数 2.1 构造函数与析构函数是否可以成为虚函数? 2.2 构造函数与析构函数是否可以发生 ...
- 关于Java中强制类型转换的问题
为了更好的理解我们先看下面的例子: package com.yonyou.test; import java.util.ArrayList; import java.util.Iterator; im ...
- java中强制类型转换时,高位数截取成低位数的方法
/** * 强制类型转换中的补码.反码.原码一搞清楚 */ int b=233;//正整数强转 System.out.println((byte)b); //负数:原码的绝对值取反再加一 符号为不变 ...
- JS中强制类型转换
JavaScript提供了3种强制类型转换的方法 一.Boolean()方法 该方法将指定的参数转换成布尔型.Boolean(object).参数object可以是字符串对象.数值对象.DOM对象等. ...
- 【Java_基础】Java中强制类型转换
首先,狭义上的强制类型转换指的是引用类型,且是父类向子类转换,这种转换只牵扯到引用名义类型的转换,具体的对象内存没有发生一点变化. 而基本类型的转换与此不同,其数据确实发生了变化.如果是基本类型和其包 ...
随机推荐
- C++ 关于滚动条的滚动问题
SCROLLINFO scrollinfo; GetScrollInfo(SB_HORZ, &scrollinfo, SIF_ALL); switch (nSBCode) { case SB_ ...
- DBCC维护语句语法
一.DBCC维护语句:对数据库.索引或文件组进行维护的任务--1.DBCC CLEANTABLE,回收删除的可变长度列和文本列的空间 DBCC CLEANTABLE ( { 'database_na ...
- Android辅助开发工具说明
1.aapt(Android Asset Packaging Tool):用于建立zip包(zip.jar.apk),也可用于将资源编译到二进制的assets:2.adb(Android Debug ...
- windows安装AnyProxy 配合夜神模拟器抓包
AnyProxy是阿里巴巴基于 Node.js 开发的一款开源代理服务器.做为中间代理服务器,它可以收集所有经过它的http请求流量(包括https明文内容):它提供了友好的web界面,便于直观的查看 ...
- 关于ros将opencv版本固定“写死”的一些想法
今天主要工作是将ros和zed结合起来,但是发现自己安装了opencv3.1,ros indigo安装的是opencv2.4.8,这就麻烦了,zed支持的是opencv3.1.一开始使用slam2时, ...
- idea 这样 会快点
最近使用IDEA来开发JAVA应用,对IDEA的界面很有爱,但是缺受不了它的运行速度.每次运行都要编译,所以就有了这边文章 总感觉IDEA的编译速度比eclipse慢,eclipse每次保存都自动 ...
- justify-content & align-items & align-content
[justify-content & align-items & align-content] 三个属性均作用于container. justify-content用于控制main-a ...
- sqlite3调试
[sqlite3调试] 1.adb shell 激活模拟器shell. 2.cd /data/data/com.xxx.xxx/databases 进入app 数据库目录. 3.ls 查看有哪些数据库 ...
- Failure [INSTALL_CANCELED_BY_USER]
安装app到真机,遇到 Failure [INSTALL_CANCELED_BY_USER] 错误. 解决方法:将手机的USB安装权限打开即可.设置->更多设置->开发者选项->US ...
- openstack(Pike 版)集群部署(八)--- 连接Ceph Cluster 作为后端存储
一.openstack Glance + ceph Cluster 部署: 博客:http://www.cnblogs.com/weijie0717/p/8563294.html 参考 续 部分. ...