C++中的新型类型转换
1,C 语言中已经有类型之间的强制转换,C++ 做了改善;
2,C 方式的强制类型转换:
1,(Type) (Expression);
2,Type (Expression);
1,这种方式和上述方式相同,但是比较古老,用的较少;
2,代码示例:
typedef void(PF)(int); struct Point
{
int x;
int y;
}; int v = 0x12345;
PF* pf = (PF*)v; // 强制类型转换为函数指针;
char c = char(v); // 老式转换,像函数调用,此时发生截断;
Point* p = (Point*)v; // 转换为结构体指针;
3,太粗暴;
3,粗暴的类型转换编程实验:
1,main.cpp 文件:
#include <stdio.h> typedef void(PF)(int); struct Point
{
int x;
int y;
}; int main()
{
int v = 0x12345;
PF* pf = (PF*)v;
char c = char(v);
Point* p = (Point*)v; pf(); printf("p->x = %d\n", p->x);
printf("p->y = %d\n", p->y); return ;
}
2,输出结果:
段错误
3,大型程序中,这种错误很难察觉;
4,C 方式强制类型转换存在的问题:
1,过于粗暴:
1,任意类型之间都可以进行强制类型转换,编译器很难判断其真确性;
2,难于定位:
1,在源代码中无法快速定位所有使用强制类型转换的语句;
2,C 方式的强制类型转换根本没有什么特征;
5,强制类型转换在实际工程中是很难完全避免的,所以要进行更加安全可靠的转换;
1,C 语言的强制类型转换已经足够简单,没有改进的余地了;
2,提出新的强制类型转换方式;
6,C++ 将强制类型转换分为 4 种不同的类型:
1,用法:xxx_cast< Type >(Exception);
2,搜索关键字可以查找代码中的强制类型转换;
7,static_cast 强制类型转换:
1,用于基本类型间的转换:
1,任何具有明确定义的类型转换,只要不包含底层 const(也就是指针或引用),都可以使用;
2,不能用于基本类型指针间的转换;
1,也就是基本类型指针的转换类型必须相同,这也就失去了指针转换的意义;
2,特殊情况除外,即把指针存放在 void* 中,并且使用 static_cast 将其强制转换回原来的类型时,应该确保指针的值保持不变,也就是地址相等,因此必须确保转换后得到的类型就是指针所指的类型;
3,用于有继承关系对象之间的转换和类指针之间的转换;
1,这里不能是顶层 const;
8,const_cast 强制类型转换:
1,用于去除变量的只读属性;
2,强制类型转换的目标类型必须是指针或引用;
1,只能改变运算对象的底层 const,其他任何转换都是错误的;
2,常常用于有函数重载的上下文中,其他情况下使用则意味某种设计缺陷,不建议;
9,reinterpret_cast 强制类型转换:
1,用于指针类型间的强制转换;
1,重解释;
2,用于整数和指针类型间的强制转换;
1,reinterpret_cast 通常为运算对象的位模式提供较低层次上的重新释;
2,reinterpret_cast 本质上依赖机器,要想安全地使用 reinterpret_cast 必须对涉及的类型和编译器实现转换的过程非常了解;
3,int* ip;
char* pc = reinterpret_cast<char*>(ip);
这里 pc 所指的真实对象是一个 int 而非字符,如果当做字符,很可能在运行时发生错误;
4,reinterpret_cast 指的是对内存中某个数据重新解释,比如可以把一个 int 数据重新解释成指针,字符型数组解释为其他类型的数组,但这里的重新解释内存大小一定要为解释目的类型的指针指向的内存大小整数倍(应改为一个倍数);
10,C++ 中旧式强制类型转换和新式强制类型转换的对应关系:
1,旧式:
1,函数形式类型转换:type (Exception);
2,C 风格类型转换:(type) Exception;
2,新式对应关系:
1,旧式类型转换分别具有与 const_cast、static_cast、reinterpret_cast 相似的行为;
2,某处执行旧式强制类型转换,如果换成 const_cast 和 static_cast 也合法,其行为与对应的命名转换一致;如果替换后不合法,则与 reinterpret_cast 功能类似;
1,char* pc = char* ip; 和 reinterpret_cast 功能类似;
11,dynamic_cast 强制类型转换:
1,用于有继承关系的类指针间的转换;
2,用于有交叉关系的类指针间的转换;
3,具有类型检查的功能;
1,如果转换不成功,得到的是空指针;
4,需要虚函数的支持;
12,新式类型转换初探实例分析:
1,main.cpp 文件:
#include <stdio.h> void static_cast_demo()
{
int i = 0x12345;
char c = 'c';
int* pi = &i;
char* pc = &c; c = static_cast<char>(i); // 可以;
// pc = static_cast<char*>(pi); // 不可以;
} void const_cast_demo()
{
const int& j = ; // 只读变量;
int& k = const_cast<int&>(j); // 去除只读变量 j 的只读属性; const int x = ; // 常量,常量虽然进入符号表,但是编译器还是会为真正意义上的常量分配空间;
int& y = const_cast<int&>(x); // 这里去掉 x 的只读属性,得到内存中为这个常量分配的内存空间,y 是空间别名;
// int z = const_cast<int>(x); //不可行,只能用于引用和指针之间; k = ; printf("k = %d\n", k);
printf("j = %d\n", j); y = ; printf("x = %d\n", x);
printf("y = %d\n", y);
printf("&x = %p\n", &x);
printf("&y = %p\n", &y);
} void reinterpret_cast_demo()
{
int i = ;
char c = 'c';
int* pi = &i;
char* pc = &c; pc = reinterpret_cast<char*>(pi); // 可行;
pi = reinterpret_cast<int*>(pc); // 可行;
pi = reinterpret_cast<int*>(i); // 可行;
c = reinterpret_cast<char>(i); // 不可行;
} void dynamic_cast_demo()
{
int i = ;
int* pi = &i;
// char* pc = dynamic_cast<char*>(pi); // 不可行;
} int main()
{
static_cast_demo();
const_cast_demo();
reinterpret_cast_demo();
dynamic_cast_demo(); return ;
}
2,输出结果:
k =
j = // j 确实是只读变量;
x = // 取符号表中的值,为了兼容 C 语言,还是在栈空间分配了四个字节的内存空间;
y = // 为四个字节空间起别名为 y;
&x = 0xbfd9a270
&y = 0xbfd9a270
3,简单的问题复杂化,是一种进化;
13,小结:
1,C 方式的强制类型转换:
1,过于粗暴;
2,潜在问题不易被发现;
3,不易在代码中定位;
2,新式类型转换以 C++ 关键字的方式出现:
1,编译器能够帮助检查潜在的问题;
2,非常方便的在代码中定位;
3,支持动态类型的识别(dynamic_cast);
C++中的新型类型转换的更多相关文章
- 5.C++里的4种新型类型转换
1首先来回顾C的强制转换 大家都知道,在编译C语言中的强制转换时,编译器不会检查转换是否成功,都会编译正确. 比如: #include "stdio.h" struct Posit ...
- 关于Java中的基本数据类型转换
Java中的基本类型有四种,其中整型分为byte.short.int.long,浮点型分为float.double,字符型char,布尔型boolean.8种类型的级别由低到高byte->sho ...
- [转]C++中四种类型转换符的总结
C++中四种类型转换符的总结 一.reinterpret_cast用法:reinpreter_cast<type-id> (expression) reinterpret_cast操 ...
- C#中的强制类型转换与as转换的区别
C#中的强制类型转换 例如有ClassA与ClassB两个类创建两个类的对象进行转换 1 2 ClassA a = new ClassA(); ClassB b = new ClassB(); 如果 ...
- 【转载】VC++中的图像类型转换--使用开源CxImage类库
一.CxImage类库简介 这只是翻译了CxImage开源项目主页上的部分简介及简单使用. CxImage类库是一个优秀的图像操作类库.它可以快捷地存取.显示.转换各种图像.有的读者可能说,有那么多优 ...
- c++ --> c++中四种类型转换方式
c++中四种类型转换方式 c风格转换的格式很简单(TYPE)EXPRESSION,但是c风格的类型转换有不少缺点, 1)它可以在任意类型之间转换,比如你可以把一个指向const对象的指针转换成指向 ...
- Java中的基本类型转换,数据溢出原理
java中的数据类型 java是一种强类型语言,在java中,数据类型主要有两大类,基本数据类型和引用数据类型,不同的数据类型有不同的数据存储方式和分配的内存大小. 基本数据类型中,各数据类型所表示的 ...
- 谈 JavaScript 中的强制类型转换 (2. 应用篇)
这一部分内容是承接上一篇的, 建议先阅读谈 JavaScript 中的强制类型转换 (1. 基础篇) 前两章讨论了基本数据类型和基本包装类型的关系, 以及两个在类型转换中十分重要的方法: valueO ...
- JS在if中的强制类型转换
JS在if中的强制类型转换 众所周知,JS在很多情况下会进行强制类型转换,其中,最常见两种是: 1.使用非严格相等进行比较,对==左边的值进行类型转换 2.在if判断时,括号内的值进行类型转换,转化为 ...
随机推荐
- 【ZJOJ5186】【NOIP2017提高组模拟6.30】tty's home
题目 分析 如果直接求方案数很麻烦. 但是,我们可以反过来做:先求出所有的方案数,在减去不包含的方案数. 由于所有的路径连在一起, 于是\(设f[i]表示以i为根的子树中,连接到i的方案数\) 则\( ...
- Linux缺少动态连接库.so--cannot open shared object file: No such file or directory
1 Liunx安装报错时,缺少动态链接库时,形式如下: /usr/local/libexec/gcc/x86_64-unknown-liunx-gnu/4.8.2/cc1: error while l ...
- Spring Boot 的各种start
新建一个springBoot项目时,你会选择很多依赖,在项目中的build.gradle中你会看见各种start,例如下边的代码: 今天就在这里列举一下各种start: 1.spring-boot-s ...
- Prim算法和Kruskal算法的正确性证明
今天学习了Prim算法和Kruskal算法,因为书中只给出了算法的实现,而没有给出关于算法正确性的证明,所以尝试着给出了自己的证明.刚才看了一下<算法>一书中的相关章节,使用了切分定理来证 ...
- python3:csv的读写
前言快要毕业那会儿,在下编写了一个招聘网站招聘岗位的爬虫提供给前女神参考,最开始我是存到mysql中,然后在到处一份csv文件给前女神.到了参加工作后,由于经常使用excel绘制图表(谁叫公司做报表全 ...
- JAVA单例模式的实现伪代码
什么是单例?:其定义是单例对象的类只能允许一个实例存在 单例的实现基本原理:1.将该类的构造方法定义为私有访问,不对外暴露从而使其他类不能实例化该类对象,只能通过该类的静态方法得到该类的唯一实例 2. ...
- android遮罩阴影对话框的实现
定义 <style name="MyDialog" parent="@android:Theme.Dialog"> <item name=&q ...
- pdf.js浏览中文pdf乱码的问题解决
由于项目中需要支持移动设备在线浏览pdf,苹果还好,天生支持,但是安卓中就不行了,需要第三方组件的支持. 这里就找到了pdf.js,由于pdf数据太多,开始的时候没法一一测试,所以随便测试打开了几篇没 ...
- 一、基础篇--1.1Java基础-int 和 Integer 有什么区别,Integer的值缓存范围
int和Integer的区别 int是基本数据类型,Integer是int的包装类. Integer必须实例化后才能使用,int变量不需要. Integer实际是对象的引用,生成一个新对象实际上是生成 ...
- 【洛谷P2016战略游戏】
树形dp的经典例题 题目描述 Bob喜欢玩电脑游戏,特别是战略游戏.但是他经常无法找到快速玩过游戏的办法.现在他有个问题. 他要建立一个古城堡,城堡中的路形成一棵树.他要在这棵树的结点上放置最少数目的 ...