简述

C++中有四个类型转换符,旨在严格限制允许的类型转换,使转换更规范。这四个转换符分别是:

  • dynamic_cast
  • static_cast
  • const_cast
  • reinterpret_cast

可以根据目的选择一个适合的运算符,而不是使用通用的类型转换。让编译器能够检查程序的行为是否与设计者想法吻合。

接下来看看每个类型转换符的用法以及它们之间的区别。

dynamic_cast

之前在 “C++之 RTTI”中讲到过dynamic_cast,dynamic_cast是动态转换,使用该转换符时会自动去检查转换类型,以及转换是否合法。它的用途是,使得能够在类层次结构中进行向上转换(由于是 is-a关系,这样的类型转换是安全的),而不允许其他转换。

语法为:
dynamic_cast<type-name> (expression)

举个栗子:
一个基类 Base(必须要是虚基类,带有虚函数),一个继承于Base 的派生类 A,那么

Base * pbase = new Base();
A * pA = new A();Base * pB = dynamic_cast\<Base*>(pA);  //成立
A * pA1 = dynamic_cast\<A*>(pbase);  //不成立

也就是说,dynamic_cast不能从多态性的虚基类强制到某个派生类或者兄弟类。dynamic_cast要求多态性的操作对象。
如果转换不合法,将会返回空指针,就比如上面那句不成立的转化,返回一个空指针。

需要注意的是:编译器不能读由 void所指向的存储提供任何保证。这也就意味着dynamic_cast不能从 void触发进行强制转换,因为它必须去查看对象,以便确定其类型,对于这种情况就需要 static_cast了。

缺点:这是为了保证转换的合法性,dynamic_cast会带来一点运行时的额外开销。

static_cast

静态转换static_cast,和dynamic_cast不同的是,它不需要检查被强制转换的对象。

语法为:
static_cast<type-name> (expression)

仅当 type_name 可被隐式转换为 expression 所属的类型或 expression 可被隐式转换为 type_name 所属的类型时,上述转换才是合法的,否则将会出错。
比如说:A 是 B 的基类,而 C 是一个无关的类,那么从 A 到 B 的转换,从 B 到 A 的转换都是合法的,而从A到 C 转换是不允许的。

A a;
B b;
A * pA = static_cast<A *>(&b);   //允许
B * pB = static_cast<B *>(&a);   //允许
C * pC = static_cast<C *>(&b);   //不允许

第一种转换是合法的,因为向上转换可以显示地进行。第二种转换是从基类指针到派生类指针,在不进行显示类型转换的情况下,将无法进行。但是由于无需进行类型转换,便可以进行另一个方向的类型转换,因此使用 static_cast 来进行向下转换是合法的。
也就是说,可以从常规基类强制,不能从虚基类强制。比如 A 如果是 B 的常规基类,没有虚函数,这样是可以向下转换的,如果 A 是B 的虚基类,就不能转换。

const_cast

const_cast运算符用于执行只有一种用途的类型转换,即改变值为 const 或 volatile,其语法也是一样的:
const_cast<type-name> (expression)

注意:这里的type-name和expression类型必须相同,除了 const 和 volatile 特征(有或无)可以不同。
比如 A 和 B 两个类:

A bar;
const A * pBar  = &bar;A * pA = const_cast<A *>(pBar);   //合法
const B * pB = const_cast<B *>(pBar);  //不合法

第一个类型转换使得*pA成为一个可用于修改 bar 的对象值的指针,它删除 const 标签,第二个类型转换是非法的,因为它同时尝试将类型从 const A * 改为 const B *.

const_cast 的用途,有时候可能需要这样一个值,它在大多数时候是常量,而有时候又是可以修改的,在这种情况下,可以将这个值声明为 const,并在需要修改它的时候,使用 const_cast 。这也可以通过通用类型转换来实现,但通用转换也可能同时改变类型:

A bar;
const A * pBar  = &bar;A * pA = (A *)(pBar);   //合法
B * pB = (B *)(pBar);  //合法

由于编程时可能无意间同时改变类型和常量特征,因此使用 const_cast运算符更安全。

但是,const_cast并不是万能的,它可以修改指向一个值的指针,但是修改 const 值的结果是不确定的,来看个示例:

#include <iostream>using namespace std;void change(const int * pt,int n)
{int * pc;pc = const_cast<int *>(pt);*pc += n;
}int main()
{int pop1 = 100;const int pop2 = 50;cout << "pop1 = " << pop1 << " pop2 = " << pop2 << endl;change(&pop1,20);change(&pop2,20);cout << "pop1 = " << pop1 << " pop2 = " << pop2 << endl;return 0;
}

输出结果:

pop1 = 100 pop2 = 50
pop1 = 120 pop2 = 50

可以看到,由于 pop2被声明为 const,因此编译器可能禁止修改它。所以 const_cast 可用来删除 const 的特征,但仅当指向的值不是 const 时才可行。

reinterpret_cast

reinterpret_cast用于天生危险的类型转换,reinterpret中文含义就是“重新诠释”,它可以用于不同类型之间的转换,也就是说可以将数据以二进制存在形式的重新解释。但并不是所有类型都可以转换的。
语法:reinterpret_cast<type-name> (expression)

示例:

struct dat{
short a;
short b;
};
long value = 0xA224B118;
dat * pd = reinterpret_cast<dat *>(&value);
cout << pd->a;

通常这样的转换适用于依赖于实现的底层编程技术,是不可移植的。例如,不同系统在存储多字节整型时,可能以不同顺序存储其中的字节。

然而,需要注意的是reinterpret_cast运算符并不支持所有的类型转换,例如,可以将指针类型转换为足以存储指针表示的整型,但不能将指针转换为更小的整型或浮点型。另一个限制是,不能将函数指针转换为数据指针,反之亦然。

什么情况下可以用到这个转换符:

  • 从指针类型到一个足够大的整数类型
  • 从整数类型或者枚举类型到指针类型
  • 从一个指向函数的指针到另一个不同类型的指向函数的指针
  • 从一个指向对象的指针到另一个不同类型的指向对象的指针
  • 从一个指向类函数成员的指针到另一个指向不同类型的函数成员的指针
  • 从一个指向类数据成员的指针到另一个指向不同类型的数据成员的指针

参考资料《c++程序设计语言》、《C++编程思想》

C++之dynamic_cast、static_cast、const_cast、reinterpret_cast的用法和区别相关推荐

  1. 【转】C++中的static_cast ,reinterpret_cast的用法和区别

    转自:https://www.cnblogs.com/heyonggang/p/3361643.html 原文地址:https://www.cnblogs.com/heyonggang/p/33616 ...

  2. C++类型转换: static_cast const_cast reinterpret_cast dynamic_cast

    * C++提供了四种新的类型强制: static_cast const_cast reinterpret_cast dynamic_cast 1)staic_cast静态强制: 不能在无关的指针之间进 ...

  3. c++ dynamic_cast,static_cast,const_cast,reinterpret_cast四种cast用法整理

    在C++中主要分为四种cast,分别是:static_cast.dynamic_cast.const_cast和reinterpret_cast dynamic_cast动态类型转换 首先,我们明确基 ...

  4. dynamic_cast, static_cast, const_cast, reinterprt_cast浅析

    用法:dynamic_cast < type-id > ( expression ) 说明:Type-id必须是类的指针.类的引用或者void *:如果type-id是指针类型,那么exp ...

  5. static_cast 和 reinterpret_cast

    <<static_cast 和 reinterpret_cast>> 作者: 阙荣文(querw@sina.com) C/C++是强类型语言,不同类型之间的相互转换是比较麻烦的 ...

  6. static_cast 和 reinterpret_cast区别

    static_cast 和 reinterpret_cast <<static_cast 和 reinterpret_cast>> 作者: 阙荣文(querw@sina.com ...

  7. C++强制类型转换:static_cast、dynamic_cast、const_cast、reinterpret_cast

    一.static_cast:static_cast<new_type> (expression) static_cast相当于传统的C语言里的强制转换,该运算符把expression转换为 ...

  8. static_cast、dynamic_cast、const_cast和reinterpret_cast总结

    前言 这篇文章总结的是C++中的类型转换,这些小的知识点,有的时候,自己不是很注意,但是在实际开发中确实经常使用的.俗话说的好,不懂自己写的代码的程序员,不是好的程序员:如果一个程序员对于自己写的代码 ...

  9. C/C++ 之 C++强制类型转换(static_cast、dynamic_cast、const_cast、reinterpret_cast)

    文章转载自:https://www.cnblogs.com/chenyangchun/p/6795923.html .在了解这块时,发现了这篇文档,感觉写的很不错! c强制转换与c++强制转换 c 语 ...

最新文章

  1. SQL2008-分页显示3种方法
  2. 如何在SecureCRT上使用公钥登陆Linux服务器
  3. Android中怎获取json,Android应用中如何解析获取的json数据
  4. oracle12537错误,ORA-12537:TNS:connection closed错误处理方法
  5. Python学习笔记_零碎知识
  6. Selenium webdriver实现原理
  7. java事务_Java 事务详解
  8. TRANCATE TABLE与DETELE TABLE的区别
  9. KeyError: 'labels [189] not contained in axis' Python DataFrame 合并后使用loc进行索引的时候出错问题分析以及解决方案
  10. IOS音视频(四十五)HTTPS 自签名证书 实现边下边播
  11. 乐2 乐视X520_官方线刷包_救砖包_解账户锁
  12. oracle对某两列求和再求和_分手后4个阶段这样挽回,再狠的他也会心软求和
  13. 冷战与战后东亚国际秩序:影响及后果
  14. qt学习总结之探索Qt的安装目录结构
  15. 凯悦250家店数据外泄 多家高端酒店存安全漏洞
  16. java的class文件批量反编译成java
  17. 【JDBC】JDBC 简介 ( JDBC 概念 | JDBC 本质 | 使用 JDBC 操作数据库的好处 | JDBC 提供的 API 组件 )
  18. Android 源码 PackageManagerService 启动流程分析
  19. oracle数据库的scn,Oracle数据库SCN详解
  20. chrome渲染流程(自己看的,写的比较乱)

热门文章

  1. 无参考评估在云信的视频测试实践
  2. 3年营收翻8倍,网易智慧企业业务多品牌战略升级
  3. AgileEAS.NET平台开发实例-药店系统-报表开发(高级篇)
  4. Windows 蠕虫首次现身 Mac 电脑:伪装成 Adobe Flash 软件
  5. mysql大表myisam的导入
  6. 1.2 Name That Number
  7. 2020 操作系统第零天复习(知识点总结)
  8. SpringCloud教程- 服务消费者(rest+ribbon)(SpringCloud版本Finchley)
  9. linux fedora35设置双系统开机启动顺序
  10. Livy安装使用(Spark rest接口服务工具)