C++相对C更严格地限制允许的类型转换,并添加4个类型转换运算符,是转换过程更规范:
* dynamic_cast;
* const_cast;
* static_cast;
* reinterpret_cast。
【dynamic_cast运算符】
假设High和Low是两个类,而ph和pl的类型分别是High*和Low*,则仅当Low是High的可访问基类(直接或间接)时,下面的语句才将一个Low*指针赋给pl:
pl = dynamic_cast<Low *> ph;
否则,该与据将空指针赋给pl。通常,该运算符的语法如下:
dynamic_cast < type-name > (expression)
该运算符的用途是,使得能够在类层析结构中进行向上转换(由于is-a关系,这样的类型转换是安全的),而不允许其他转换。
【const_cast运算符】
const_cast运算符用于执行只有一种用途的类型转换,即改变值为const或volatile,其语法与dynamic_cast运算符相同。
const_cast < type_name > (expression)
如果类型的其他方面也被修改,则上述类型转换将出错。也就是说,除了const或volatile特征(有或无)可以不同外,type_name和expression的类型必须向同。再次假设High和Low是两个类:
High bar;
const High * pbar = &bar;
...
High * pb = const_cast<High *> (pbar);    // valid
const Low * pl = const_cast<const Low *> (pbar);    // invalid
第一个类型转换使得*pb称为一个可用于修改bar对象值的指针,它删除const标签。第二个类型转换是非法的,因为它同时尝试将类型从const High*改为const Low*。
提供运算符的原因是,有时候可能需要这样一个值,它在大多数时候是常量,而有时又是可以修改的。在这种情况下,可以将这个值声明为const,并在需要修改它的时候,使用const_cast。这也可以通过类型转换来实现,单通用转换也可以同时改变类型(这里的意思是const_cast不能同时改变类型):
High bar;
const High * pbar = &bar;
...
High * pb = (High *) (pbar);    // valid
Low * pl = (Low *) (pbar);    // also valid
由于编程时可能无意间同时该便类型和常量特征,因此使用const_cast运算符更安全。
【static_cast运算符】
static_cast运算符的语法与其他类型转换运算符相同:
static_cast < type_name > (expression)
仅当type_name可被隐式转换为expression所属的类型或expression可被隐式转换为type_name所属的类型时,上述转换才是合法的,否则将出错。假设High是Low的基类,而Pond是一个无关的类,则从High到Low的转换、从Low到High的转换都是合法的,而从Low到Pond的转换是不允许的:
High bar;
Low blow;
...
High *pb = static_cast<High *> (&blow);        // valid upcast
Low * pl = static_cast<Low *> (&bar);        // valid downcast
Pond * pmer = static_cast<Pond *> (&blow);    // invalid, Pond unrelated
第一种转换是合法的,因为向上转换可以显式地进行。第二种转换是从基类指针到派生类指针,在不进行显式类型转换的情况下,将无法进行。单由于无需进行类型转换,便可以进行另一个方向的类型转换,因此使用static_cast来进行向下转换是合法的。
同理,由于无须进行类型转换,枚举值就可以被转换为整型,所以可以用static_cast将整型转换为枚举型。同样,可以使用static_cast将double转换为int、将float转换为long以及其他各种数值转换。
【reinterpret_cast运算符】
reinterpret_cast运算符用于天生危险的类型转换。它不允许删除const,但会执行其他令人生厌的操作。有时程序员必须做一些依赖于实现的、令人生厌的操作,使用reinterpret_cast运算符可以简化对这种行为的跟踪工作。该运算符的语法与另外3个相同:
reinterpret_cast < type-name > (expression)
下面是一个使用示例:
struct dat {short a; short b;};
long value = 0xA224B118;
dat * pd = reinterpret_cast< dat * > (&value);
cout << hex << pd->a;    // display first 2 bytes of value
通常,这样的转换适用于依赖于实现的底层编程技术,是不可移植的。例如,不同系统在存储多字节整型时,可能以不同的顺序存储其中的字节。
然而,reinterpret_cast运算符并不支持所有的类型转换。例如,可以将指针类型转换为足以存储指针表示的整型,单不能将指针转换为更小的整型或浮点型。另一个限制是,不能将函数指针转换为数据指针,反之亦然。

在C++中,普通类性转换也受到限制。基本上,可以执行其他类型转换可执行的操作,加上一些组合,如static_cast或reinterpret_cast后跟const_cast,但不能执行其他转换。因此,下面的类型转换在C语言中是允许的,但在C++中通常不允许,因为对于大多数C++实现,char类型都太小,不能存储指针:
char ch = char (&d);    // type cast #2 - convert address to a char

《C++ Primer Plus》15.5 类型转换运算符 学习笔记的更多相关文章

  1. 《C++ Primer Plus》14.3 多重继承 学习笔记

    多重继承(MI)描述的是有多个直接基类的类.与单继承一样,共有MI表示的也是is-a关系.例如,可以从Awiter类和Singer类派生出SingingWaiter类:class SingingWai ...

  2. 【C++】类型转换(学习笔记)

    1. 隐式类型转换,相关联的类型(e.g.int vs double)之间可以发生隐式类型转换. 比如,在条件中,非布尔类型转为布尔类型: 初始化时,初始值变为变量类型: 赋值时,右值变成左侧的类型: ...

  3. C语言运算符学习笔记

    运算符不仅具有不同的优先级,还有不同的结合性.在表达式中,各运算量参与运算的先后顺序不仅要遵守运算符优先级别的规定,还要受运算符结合性的制约,以便确定是自左向右进行运算还是自右向左进行运算. C语言的 ...

  4. 《C++ Primer Plus》16.4 泛型编程 学习笔记

    STL是一种泛型编程(generic programming).面向对象编程关注的是编成的数据方面,而泛型编程关注的是算法.它们之间的共同点是抽象和创建可重用代码,单他们的理念决然不同.泛型编程旨在编 ...

  5. 《C++ Primer Plus》第6章 学习笔记

    使用引导程序选择不同操作的语句后,程序和编程将更有趣.C++提供了if 语句 .if else 语 句 和 switch 语句来管理选项.if 语句使程序有条件地执行语句或语句块,也就是说,如果满足特 ...

  6. 《C++ Primer Plus》第4章 学习笔记

    数组.结构和指针是C++的3中符合类型.数组可以在一个数据对象中存储多个同种类型的值.通过使用索引或下标,可以访问数组中各个元素.结构可以将多个不同类型的值存储在同一个数据对象中,可以使用成员关系运算 ...

  7. javaScript运算符学习笔记

    1.赋值运算符 javaScript运算符可以分为简单赋值和复合赋值运算.简单赋值运算是将赋值运算符(=)右边的表达式的值保存到赋值运算符左边的变量中,复合赋值运算则是混合了其他操作(算术运算操作,位 ...

  8. 《C++ Primer Plus 第6版》学习笔记

    第三章.基本数据类型 整形 short:至少16位 int:至少与short一样长 long:至少32位,且至少与int一样长 long long:至少64位,且至少与long一样长 字符类型 cha ...

  9. 2018/2/15 ES Beats的学习笔记

    Beats其实是几种服务的统称(你也可以把收集到的数据存储到别的数据源,不一定非要ES),这几种服务分别是: 1.PacketBeat 通过抓包的方式来监控一些服务.如:HTTP,DNS,Redis, ...

随机推荐

  1. C#写的工厂模式

    program.cs file using System; using System.Collections.Generic; using System.Text; namespace Console ...

  2. js获取相同name文本框的value

    <html xmlns="http://www.w3.org/1999/xhtml"><head runat="server"> < ...

  3. vim 移植记录

    下载两个源码包: vim : ftp://ftp.vim.org/pub/vim/unix/vim-7.4.tar.bz2\ ncurses-5.8.tar.gz http://ftp.gnu.org ...

  4. Windows 2008 R2组策略之二——GPO初探

    与前一篇博文发表已经相去月余了,实在是有些不好意思了.感谢51CTO的大编们将小文加了推荐,这使我更加觉得自己产出太少,难于回馈大家的厚爱. 今天将这个系列的第二篇奉献给大家,以伺视听. 在上篇小文中 ...

  5. Zookeeper使用场景

    分布式系统的运行是很复杂的,因为涉及到了网络通信还有节点失效等不可控的情况.下面介绍在最传统的master-workers模型,主要可以会遇到什么问题,传统方法是怎么解决以及怎么用zookeeper解 ...

  6. ScriptX使用

    自己研究了一下ScriptX并且做了个事例,希望可以帮到需要的同学 下载地址: http://download.csdn.net/detail/jine515073/7234575

  7. The Qt Resource System

    The Qt Resource System The Qt resource system is a platform-independent mechanism for storing binary ...

  8. rufus/scheduler

    之前先在initializers 文件夹下建立了一个task.rb ,rails服务启动的时候执行,本地没问题,可是服务器上启动了3个进程,会执行3遍,解决方法是 把task.rb 放到 script ...

  9. ubuntu 12.04 rails server 时候报错 execjs

    新的应用创建好了,使用rails server启动看看,oops!原来是没有javascript运行环境. 1 2 $ rails server  /usr/local/lib/ruby/gems/1 ...

  10. 基于Dedup的数据打包技术

    基于Dedup的数据打包技术 0.引言    Tar, winrar, winzip是最为常见的数据打包工具软件,它们把文件集体封装成一个单独的数据包,从而方便数据的分布.传输.归档以及持久保存等目的 ...