Q:什么是C风格转换?什么是static_cast, dynamic_cast 以及 reinterpret_cast?区别是什么?为什么要注意?

A:转换的含义是通过改变一个变量的类型为别的类型从而改变该变量的表示方式。为了类型转换一个简单对象为另一个对象你会使用传统的类型转换操作符。比如,为了转换一个类型为doubole的浮点数的指针到整型:
代码:

int i;
double d;
i = (int) d;

或者:

i = int (d);

对于具有标准定义转换的简单类型而言工作的很好。然而,这样的转换符也能不分皂白的应用于类(class)和类的指针。ANSI-C++标准定义了四个新的转换符:’reinterpret_cast’, ‘static_cast’, ‘dynamic_cast’ 和 ‘const_cast’,目的在于控制类(class)之间的类型转换。
代码:

reinterpret_cast<new_type>(expression)
dynamic_cast<new_type>(expression)
static_cast<new_type>(expression)
const_cast<new_type>(expression)

1 reinterpret_cast

‘reinterpret_cast’转换一个指针为其它类型的指针。它也允许从一个指针转换为整数类型。反之亦然。(译注:是指针具体的地址值作为整数值?)
这个操作符能够在非相关的类型之间转换。操作结果只是简单的从一个指针到别的指针的值的二进制拷贝。在类型之间指向的内容不做任何类型的检查和转换。

如果情况是从一个指针到整型的拷贝,内容的解释是系统相关的,所以任何的实现都不是方便的。一个转换到足够大的整型能够包含它的指针是能够转换回有效的指针的。

代码:

class A {};
class B {};A * a = new A;
B * b = reinterpret_cast<B *>(a);
'reinterpret_cast'就像传统的类型转换一样对待所有指针的类型转换。

2 static_cast

‘static_cast’允许执行任意的隐式转换和相反转换动作。(即使它是不允许隐式的)

应用到类的指针上,意思是说它允许子类类型的指针转换为父类类型的指针(这是一个有效的隐式转换),同时,也能够执行相反动作:转换父类为它的子类。

在这最后例子里,被转换的父类没有被检查是否与目的类型相一致。
代码:

class Base {};
class Derived : public Base {};Base *a    = new Base;
Derived *b = static_cast<Derived *>(a);

‘static_cast’除了操作类型指针,也能用于执行类型定义的显式的转换,以及基础类型之间的标准转换:

代码:

double d = 3.14159265;
int    i = static_cast<int>(d);

3 dynamic_cast

‘dynamic_cast’只用于对象的指针和引用。当用于多态类型时,它允许任意的隐式类型转换以及相反过程。不过,与static_cast不同,在后一种情况里(注:即隐式转换的相反过程),dynamic_cast会检查操作是否有效。也就是说,它会检查转换是否会返回一个被请求的有效的完整对象。
检测在运行时进行。如果被转换的指针不是一个被请求的有效完整的对象指针,返回值为NULL.
代码:

class Base { virtual dummy() {} };
class Derived : public Base {};Base* b1 = new Derived;
Base* b2 = new Base;Derived* d1 = dynamic_cast<Derived *>(b1);          // succeeds
Derived* d2 = dynamic_cast<Derived *>(b2);          // fails: returns 'NULL'

如果一个引用类型执行了类型转换并且这个转换是不可能的,一个bad_cast的异常类型被抛出:
代码:

class Base { virtual dummy() {} };
class Derived : public Base { };Base* b1 = new Derived;
Base* b2 = new Base;Derived d1 = dynamic_cast<Derived &*>(b1);          // succeeds
Derived d2 = dynamic_cast<Derived &*>(b2);          // fails: exception thrown

4 const_cast

这个转换类型操纵传递对象的const属性,或者是设置或者是移除:
代码:

class C {};const C *a = new C;C *b = const_cast<C *>(a);

其它三种操作符是不能修改一个对象的常量性的。
注意:’const_cast’也能改变一个类型的volatile qualifier。


C++的4种类型转换

一、C 风格(C-style)强制转型如下:

(T) expression // cast expression to be of type T
函数风格(Function-style)强制转型使用这样的语法:
T(expression) // cast expression to be of type T
这两种形式之间没有本质上的不同,它纯粹就是一个把括号放在哪的问题。我把这两种形式称为旧风格(old-style)的强制转型。

二、 C++的四种强制转型形式:

  C++ 同时提供了四种新的强制转型形式(通常称为新风格的或 C++ 风格的强制转型):
  const_cast(expression)
  dynamic_cast(expression)
  reinterpret_cast(expression)
  static_cast(expression)

  每一种适用于特定的目的:
  ·dynamic_cast 主要用于执行“安全的向下转型(safe downcasting)”,也就是说,要确定一个对象是否是一个继承体系中的一个特定类型。它是唯一不能用旧风格语法执行的强制转型,也是唯一可能有重大运行时代价的强制转型。
·static_cast 可以被用于强制隐型转换(例如,non-const 对象转型为 const 对象,int 转型为 double,等等),它还可以用于很多这样的转换的反向转换(例如,void* 指针转型为有类型指针,基类指针转型为派生类指针),但是它不能将一个 const 对象转型为 non-const 对象(只有 const_cast 能做到),它最接近于C-style的转换。
  ·const_cast 一般用于强制消除对象的常量性。它是唯一能做到这一点的 C++ 风格的强制转型。
  ·reinterpret_cast 是特意用于底层的强制转型,导致实现依赖(implementation-dependent)(就是说,不可移植)的结果,例如,将一个指针转型为一个整数。这样的强制转型在底层代码以外应该极为罕见。
  
  旧风格的强制转型依然合法,但是新的形式更可取。首先,在代码中它们更容易识别(无论是人还是像 grep 这样的工具都是如此),这样就简化了在代码中寻找类型系统被破坏的地方的过程。第二,更精确地指定每一个强制转型的目的,使得编译器诊断使用错误成为可能。例如,如果你试图使用一个 const_cast 以外的新风格强制转型来消除常量性,你的代码将无法编译。

dynamic_cast .vs. static_cast

class B { ... };
class D : public B { ... };void f(B* pb)
{D* pd1 = dynamic_cast<D*>(pb);D* pd2 = static_cast<D*>(pb);
}

If pb really points to an object of type D, then pd1 and pd2 will get the same value. They will also get the same value if pb == 0.

If pb points to an object of type B and not to the complete D class, then dynamic_cast will know enough to return zero. However, static_cast relies on the programmer’s assertion that pb points to an object of type D and simply returns a pointer to that supposed D object.

即dynamic_cast可用于继承体系中的向下转型,即将基类指针转换为派生类指针,比static_cast更严格更安全。dynamic_cast在执行效率上比static_cast要差一些,但static_cast在更宽上范围内可以完成映射,这种不加限制的映射伴随着不安全性.static_cast覆盖的变换类型除类层次的静态导航以外,还包括无映射变换,窄化变换(这种变换会导致对象切片,丢失信息),用VOID*的强制变换,隐式类型变换等...

static_cast .vs. reinterpret_cast

reinterpret_cast是为了映射到一个完全不同类型的意思,这个关键词在我们需要把类型映射回原有类型时用到它.我们映射到的类型仅仅是为了故弄玄虚和其他目的,这是所有映射中最危险的.(这句话是C++编程思想中的原话)static_cast 和 reinterpret_cast 操作符修改了操作数类型. 它们不是互逆的; static_cast 在编译时使用类型信息执行转换, 在转换执行必要的检测(诸如指针越界计算, 类型检查). 其操作数相对是安全的. 另一方面, reinterpret_cast 仅仅是重新解释了给出的对象的比特模型而没有进行二进制转换, 例子如下:int n=9; double d=static_cast < double > (n); 上面的例子中, 我们将一个变量从 int 转换到 double. 这些类型的二进制表达式是不同的. 要将整数 9 转换到 双精度整数 9, static_cast 需要正确地为双精度整数 d 补足比特位. 其结果为 9.0. 而reinterpret_cast 的行为却不同: int n=9;
double d=reinterpret_cast<double & > (n); 这次, 结果有所不同. 在进行计算以后, d 包含无用值. 这是因为 reinterpret_cast 仅仅是复制 n 的比特位到 d, 没有进行必要的分析.

总结:
一共四种cast。1、static_cast,支持子类指针到父类指针的转换,并根据实际情况调整指针的值,反过来也支持,但会给出编译警告,它作用最类似C风格的“强制转换”,一般来说可认为它是安全的;2、dynamic_cast,支持父类指针到子类指针的转换,并根据实际情况调整指针的值,和static_cast不同,反过来它就不支持了,会导致编译错误,这种转换是最安全的转换;3、reinterpret_cast,支持任何转换,但仅仅是如它的名字所描述的那样“重解释”而已,不会对指针的值进行任何调整,用它完全可以做到“指鹿为马”,但很明显,它是最不安全的转换,使用它的时候,你得头脑清醒,知道自己在干什么;4、const_cast,这个转换能剥离一个对象的const属性,也就是说允许你对常量进行修改。

C++中的四种类型转化相关推荐

  1. TLD文件中body-content四种类型(能力工场)

    tagdependent:标签体内容直接被写入BodyContent,由自定义标签类来进行处理,而不被JSP容器解释, 如下: <test:myList> select name,age ...

  2. C#中方法参数的四种类型

    C#中方法的参数有四种类型: -值参数:不含任何修饰符.方法中的形参是实参的一份拷贝,形参的改变不会影响到内存中实参的的值,实参是安全的. -引用参数:以ref修饰符声明.传递的参数实际上是实参的指针 ...

  3. C#中方法的参数的四种类型(转)

    转自:http://www.cnblogs.com/netlyf/p/3822956.html C#中方法的参数有四种类型: 1. 值参数类型  (不加任何修饰符,是默认的类型) 2. 引用型参数   ...

  4. java类型转换答案,在java中支持两种类型的类型转换,自动类型转换和强制类型转换。父类转化为子类需要强制转换。...

    在java中支持两种类型的类型转换,自动类型转换和强制类型转换.父类转化为子类需要强制转换. 更多相关问题 计算机病毒通过()传染扩散得极快,危害最大. 当一个现象的数量由小变大,另一个现象的数量相反 ...

  5. 【整理】Python中的re.search和re.findall之间的区别和联系 + re.finall中带命名的组,不带命名的组,非捕获的组,没有分组四种类型之间的区别

    之前自己曾被搞晕过很多次. 后来使用这些函数次数多了之后,终于比较清楚的弄懂了两者之间的区别和关系了. 尤其是一些细节方面的注意事项了. 在看下面的总结和代码之前,请先确保你对如下基本概念已经有所了解 ...

  6. 四种类型的数据分析模式

    在这篇博文中,我们聚焦于在数据科学领域所遇到的四种类型的数据分析模式:描述型.诊断型.预测型和指导型. 当我与刚涉足数据科学领域的年轻分析师们交谈时,通常,我会问他们认为什么是数据科学家最重要的能力. ...

  7. C++四种类型强制转换——const_cast、static_cast、dynamic_cast、reinterpret_cast

    文章目录 一.const_cast 1.基本知识 2.示例演示 二.static_cast 1.基本知识 2.示例演示 三.dynamic_cast 1.基本知识 2.示例演示 四.reinterpr ...

  8. 地铁闸门会夹伤人吗_西安地铁率先推出分类垃圾箱 四种类型你会放吗?

    垃圾分类就是新时尚[西安地铁率先推出分类垃圾箱 四种类型你会放吗?]近日,不少上海人已被垃圾分类"逼疯",各类段子刷爆网络."你是什么垃圾?"直击灵魂深处的拷问 ...

  9. Java 中的四种引用

    垃圾收集器与内存分配策略参考目录: 1.判断Java 对象实例是否死亡 2. Java 中的四种引用 3.垃圾收集算法 4. Java9中的GC 调优 5.内存分配与回收策略 在进行垃圾回收之前,虚拟 ...

最新文章

  1. 10 大受欢迎的全球顶级编程语言与薪资水平
  2. Java进阶学习资料!dockerjar内存
  3. java文件 linux_Linux执行Java文件
  4. hadoop hive hbase 入门学习 (二)
  5. Mysql学习总结(32)——MySQL分页技术详解
  6. SqlServer命名规范
  7. cisco路由器IOS灾难恢复
  8. 计算机专业毕业论文题目大全集
  9. libtorch-gpu推理时占用CPU 100%问题解决
  10. 如果unity双击无法打开怎么办
  11. 卫星通信 | 使用虹科SAF手持式频谱分析仪进行TDD信号分析
  12. 【论文笔记】Exploring Self-attention for Image Recognition
  13. android 镜像投屏开发,Android 投屏实现纪要
  14. vite 预编译实现
  15. 如何对研发团队绩效进行考核--附各环节人员考核参考表
  16. 七牛云存对象存储及域名设置
  17. 如何删除Win10“此电脑”中多出的“CD驱动器”盘符
  18. axure图标元件库icons满足不了需求?[一分钟教会你在axure下使用各式各样炫酷icons]!! 仅限谷歌浏览器
  19. ubuntu 16.04 无法连接wifi
  20. 安排软件保护服务在 2022-07-26T23:00:43Z 时重新启动成功。原因: RulesEngine

热门文章

  1. win7 计算机属性 灰,win7系统文件夹属性中隐藏选项显示灰色不可改的解决方法...
  2. zip()函数以及编程题:最长公共前缀(代码简单易懂)
  3. 微信第三方平台开发流程和总结
  4. Linux Namespace系列(06):network namespace (CLONE_NEWNET)
  5. 【46】SSD硬盘(上):如何完成性能优化的KPI?
  6. 微积分:极限的定义、夹逼定理
  7. Win11找不到realtek高清晰音频管理器怎么办?
  8. Gionee/金立C500 root教程_方法
  9. 华为android10手机指纹,华为手机如何设置指纹解锁?华为手机锁屏密码设置教程...
  10. Android usb host