1 由于强制转型无所不能,会给C++ 程序带来很大的安全隐患,因此建议在C++ 代码中,努力将强制转型减到最少

将较大的整数转换为较短的数据类型时,会产生无意义的结果,而程序员可能被蒙在鼓里。正如下面的代码片段所示:
unsigned i = 65535;
int j = (int) i;
输出结果竟然成了-1。较长的无符号类型在转换为较短的有符号类型时,其数值很可能会超出较短类型的数值表示范围。编译器不会监测这样的错误,它所能做的仅仅是抛出一
条非安全类型转换的警告信息。如果这样的问题发生在运行时,那么一切会悄无声息,系统既不会中断,也不会出现任何的出错信息。

类似的问题还会发生在有符号负数转化为无符号数、双精度类型转化为单精度类型、浮点数转化为整型等时候。以上这些情况都属于数值的强制转型,在转换过程中,首先生成临时变量,然后会进行数值截断。

在标准C 中,强制转型还有可能导致内存扩张与截断。这是因为在标准C 中,任何非void 类型的指针都可以和void 类型的指针相互指派,也就可以通过void 类型指针这个中介,实现不同类型的指针间接相互转换了。代码如下所示:
double PI = 3.1415926;
double *pd = Π
void *temp = pd;
int *pi = temp; // 转换成功
指针pd 指向的空间本是一个双精度数据,8 字节。但是经过转换后,pi 却指向了一个4 字节的int 类型。这种发生内存截断的设计缺陷会在转换后进行内存访问时存在安全隐患。不过,这种情况只会发生在标准C 中。在C++ 中,设计者为了杜绝这种错误的出现,规定了不同类型的指针之间不能相互转换,所以在使用纯C++ 编程时大可放心。而如果C++ 中嵌入了部分C 代码,就要注意因强制转型而带来的内存扩张或截断了。与旧风格的强制转型相对应的就是新风格的强制转型了,在C++ 提供了如下四种形式:

const_cast(expression)
dynamic_cast(expression)
reinterpret_cast(expression)
static_cast(expression)
新风格的强制转型针对特定的目的进行了特别的设计,如下所示。
const_cast<T*> (a)
它用于从一个类中去除以下这些属性:const、volatile 和 __unaligned。
class A { // … };
void Function()
{

const A *pConstObj = new A;
A *pObj = pConstObj; //ERROR: 不能将const 对象指针赋值给非const 对象
pObj = const_cast<A*>( pConstObj); // OK
//...
}
这种强制转型的目的简单明确,使用情形比较单一,易于掌握。

dynamic_cast<T*>(a)
它将a 值转换成类型为T 的对象指针,主要用来实现类层次结构的提升,在很多书中它被称做“安全的向下转型(Safe Downcasting)”,用于继承体系中的向下转型,将基类指针转换为派生类指针,这种转换较为严格和安全。
如下面的代码片段所示:
class B { //... };
class D : public B { //... };
void Function(D *pObjD)
{
D *pObj = dynamic_cast<D*>( pObjD);
//...
}
如果pObjD 指向一个D 类型的对象,pObj 则指向该对象,所以对该指针执行D 类型的任何操作都是安全的。但是,如果pObjD 指向的是一个B 类型的对象,pObj 将是一个空指针,这在一定程度上保证了程序员所需要的“安全”,只是,它也付出了一定的运行时代价,而且代价非常大,实现相当慢。有一种通用实现是通过对类名称进行字符串比较来实现的,只是其在继承体系中所处的位置越深,对strcmp 的调用就越多,代价也就越大。如果应用对性能要求较高,那么请放弃dynamic_cast。
reinterpret_cast<T*>(a)
它能够用于诸如One_class* 到 Unrelated_class* 这样的不相关类型之间的转换,因此它
是不安全的。其与C 风格的强制转型很是相似。
class A { // ... };
class B { //... };
void f()
{
A* pa = new A;
B* pb = reinterpret_cast<B*>(pa);
// ...

}
在不了解A、B 内存布局的情况下,强行将其进行转换,很有可能出现内存膨胀或截断。
static_cast<T*>(a)
它将a 的值转换为模板中指定的类型T。但是,在运行时转换过程中,它不会进行类型
检查,不能确保转换的安全性。
如下面的代码片段所示:
class B { ... };
class D : public B { ... };
void Function(B* pb, D* pd)
{
D* pd2 = static_cast<D*>(pb); // 不安全
B* pb2 = static_cast<B*>(pd); // 安全的
}
之所以说第一种是不安全的,是因为如果pb 指向的仅仅是一个基类B 的对象,那么就
会凭空生成继承信息。至于这些信息是什么、正确与否,无从得知。所以对它进行D 类型的
操作将是不安全的。
C++ 是一种强类型的编程语言,其规则设计为“保证不会发生类型错误”。在理论层面
上,如果希望程序顺利地通过编译,就不应该试图对任何对象做任何不安全的操作。不幸的
是,继承自C 语言的强制转型破坏了类型系统,所以建议尽量少地使用强制转型,无论是旧
的C 风格的还是新的C++ 风格的。如果发现自己使用了强制转型,那么一定要小心,这可
能就是程序出现问题的一个信号。

2012.4.16总结(三)相关推荐

  1. 2012 不宜进入的三个技术点

    http://blog.csdn.net/lanphaday/article/details/7217506 2012 不宜进入的三个技术点(上) 赖勇浩( http://laiyonghao.com ...

  2. 使用ContactsContract APIhttp://www.cnblogs.com/carbs/archive/2012/07/16/2593295.html

    转自:http://www.cnblogs.com/carbs/archive/2012/07/16/2593295.html 自Android 2.0(API Level 5)开始,Android平 ...

  3. 2012 不宜进入的三个技术点(下)

    赖勇浩(http://laiyonghao.com) C++ C++ 在 2011 年其实风头甚劲,C++2011 标准出台,gcc/msvc/clang 都很快速地支持了许多新特性,新兴的移动设备的 ...

  4. DWR入门教程(http://www.cnblogs.com/cyjch/archive/2012/02/16/2353758.html)

    文章转载自<http://www.cnblogs.com/cyjch/archive/2012/02/16/2353758.html>,多谢大牛分享! DWR入门教程 DWR(Direct ...

  5. http://www.cnblogs.com/xia520pi/archive/2012/05/16/2504205.html

    http://www.cnblogs.com/xia520pi/archive/2012/05/16/2504205.html http://www.cnblogs.com/madyina/p/370 ...

  6. 第16节 三个败家子(16)—— 曹魏灭亡

    第16节 三个败家子(16)-- 曹魏灭亡 少主当朝,在任何朝代都是极其危险的--更何况是以幼主处乱世,此时权力的真空要么由外戚占据; 要么由权臣填补. 虽然曹叡按照"托孤游戏规则" ...

  7. 2012.4.16总结(二)

    1 表达式的求值顺序问题: 函数参数的评估求值顺序 分析下面代码片段的输出结果: int i = 2010; printf("The results are: %d %d", i, ...

  8. ][互动大奖] Webby Awards 2012 第16届威比奖

    http://blog.sina.com.cn/s/blog_59fe4e920102eb7q.html 素有"互动界的奥斯卡奖"称号的Webby Awards威比奖历来是国际公认 ...

  9. 2012 不宜进入的三个技术点(上)

    赖勇浩( http://laiyonghao.com) 其实写这篇博客的想法在年前已经有了,但一直在犹豫要不要写,一是因为写出来肯定会有人骂的了,刚过完春节的,在自己地头找骂,实在是晦气:二是因为我对 ...

最新文章

  1. fpga数据位宽截取_FPGA信号截位策略研究
  2. C#中将dll汇入exe,并加壳
  3. libcoredb.class.php,ThinkPHP/Lib/Core/Db.class.php中pdo处理逻辑似乎不完善,导致config中pdo配置失效...
  4. 深入理解Auto Layout 第一弹
  5. VC++ MsChart控件怎么用?
  6. BAT自动IP地址切换脚本
  7. 【MODBUS】组态王通过串口与MODBUS RTU设备通讯
  8. Java 枚举类转换List
  9. 社群编码识别黑灰产攻击实践
  10. linux查看本机IP掩码,linux下 取得本机ip、掩码、网关
  11. Python数据分析!NBA的球星们喜欢在哪个位置出手!
  12. 一堆比B站还刺激的公众号!
  13. 搬砖(二分答案 + 线性规划)
  14. 如何使移动设备字体大小自适应
  15. Ajax vs Willem II,Ajax is bedrijfsongeval weer te boven
  16. js实现刷新当前页面
  17. webpack.base.conf.js文件
  18. react总结之jsx是什么,jsx语法规则
  19. vbs计算机病毒代码,求最全的vbs病毒代码,要破坏性的。谢谢,回答的好我多给分。...
  20. pycharm使用-venv环境创建

热门文章

  1. Go本地浏览Web服务器
  2. bat之启动与禁用网卡
  3. 搭建MyEclipse和Tomcat遇到的坑(JavaEE作业)
  4. python对象的引用_Python 对象引用、可变性和垃圾回收
  5. Android Studio如何去除界面默认标题栏
  6. 编译原理 - SLR(1)
  7. vue子组件mounted不执行_vue中父子组件传值,解决钩子函数mounted只运行一次的问题...
  8. 英国python工资_在伦敦金融城当数据分析师-Python篇
  9. visual studio可以开发app吗_郑州app开发价格是怎么定得呢?预约理发app好做吗
  10. anaconda安装numpy_Python3.8如何安装Numpy