一.static_cast

static_cast 只能用于良性转换,这样的转换风险较低,一般不会发生什么意外,如:

  1. #include <iostream>
  2. #include <cstdlib>
  3. using namespace std;
  4.  
  5. class Complex{
  6. public:
  7. Complex(double real = 0.0, double imag = 0.0): m_real(real), m_imag(imag){ }
  8. public:
  9. operator double() const { return m_real; } //类型转换函数
  10. private:
  11. double m_real;
  12. double m_imag;
  13. };
  14.  
  15. int main(){
  16. //下面是正确的用法
  17. int m = ;
  18. Complex c(12.5, 23.8);
  19. long n = static_cast<long>(m); //宽转换,没有信息丢失
  20. char ch = static_cast<char>(m); //窄转换,可能会丢失信息
  21. int *p1 = static_cast<int*>( malloc( * sizeof(int)) ); //将void指针转换为具体类型指针
  22. void *p2 = static_cast<void*>(p1); //将具体类型指针,转换为void指针
  23. double real= static_cast<double>(c); //调用类型转换函数
  24.  
  25. //下面的用法是错误的
  26. float *p3 = static_cast<float*>(p1); //不能在两个具体类型的指针之间进行转换
  27. p3 = static_cast<float*>(0X2DF9); //不能将整数转换为指针类型
  28.  
  29. return ;
  30. }

二.const_cast

const_cast用来去掉表达式的 const 修饰或 volatile 修饰。换句话说,const_cast 就是用来将 const/volatile 类型转换为非 const/volatile 类型。如:

  1. #include <iostream>
  2. using namespace std;
  3.  
  4. int main(){
  5. const int n = ;
  6. int *p = const_cast<int*>(&n);
  7. *p = ;
  8. cout<<"n = "<<n<<endl;
  9. cout<<"*p = "<<*p<<endl;
  10.  
  11. return ;
  12. }

运行结果:

n = 100
*p = 234

&n用来获取 n 的地址,它的类型为const int *,必须使用 const_cast 转换为int *类型后才能赋值给 p。由于 p 指向了 n,并且 n 占用的是栈内存,有写入权限,所以可以通过 p 修改 n 的值。

至于为什么通过 n 和 *p 输出的值不一样呢?这是因为 C++ 对常量的处理更像是编译时期的#define,是一个值替换的过程,代码中所有使用 n 的地方在编译期间就被替换成了 100。换句话说,第 8 行代码被修改成了下面的形式:

  1. cout<<"n = "<<<<endl;

这样以来,即使程序在运行期间修改 n 的值,也不会影响 cout 语句了。

三.reinterpret_cast

reinterpret_cast 这种转换仅仅是对二进制位的重新解释,不会借助已有的转换规则对数据进行调整,非常简单粗暴,所以风险很高

  1. #include <iostream>
  2. using namespace std;
  3.  
  4. class A{
  5. public:
  6. A(int a = , int b = ): m_a(a), m_b(b){}
  7. private:
  8. int m_a;
  9. int m_b;
  10. };
  11.  
  12. int main(){
  13. //将 char* 转换为 float*
  14. char str[]="http://c.biancheng.net";
  15. float *p1 = reinterpret_cast<float*>(str);
  16. cout<<*p1<<endl;
  17. //将 int 转换为 int*
  18. int *p = reinterpret_cast<int*>();
  19. //将 A* 转换为 int*
  20. p = reinterpret_cast<int*>(new A(, ));
  21. cout<<*p<<endl;
  22.  
  23. return ;
  24. }

运行结果:

3.0262e+29

个人感觉这个关键字很危险,所以不推荐使用.

四.dynamic_cast

dynamic_cast 用于在类的继承层次之间进行类型转换,它既允许向上转型(Upcasting),也允许向下转型(Downcasting)。向上转型是无条件的,不会进行任何检测,所以都能成功;向下转型的前提必须是安全的,要借助 RTTI 进行检测,所有只有一部分能成功。

有以下两点需要注意:

1).newType 和 expression 必须同时是指针类型或者引用类型。换句话说,dynamic_cast 只能转换指针类型和引用类型,其它类型(int、double、数组、类、结构体等)都不行。

2).对于指针,如果转换失败将返回 NULL;对于引用,如果转换失败将抛出std::bad_cast异常。

例:

  1. #include <iostream>
  2. using namespace std;
  3.  
  4. class A{
  5. public:
  6. virtual void func() const { cout<<"Class A"<<endl; }
  7. private:
  8. int m_a;
  9. };
  10.  
  11. class B: public A{
  12. public:
  13. virtual void func() const { cout<<"Class B"<<endl; }
  14. private:
  15. int m_b;
  16. };
  17.  
  18. class C: public B{
  19. public:
  20. virtual void func() const { cout<<"Class C"<<endl; }
  21. private:
  22. int m_c;
  23. };
  24.  
  25. class D: public C{
  26. public:
  27. virtual void func() const { cout<<"Class D"<<endl; }
  28. private:
  29. int m_d;
  30. };
  31.  
  32. int main(){
  33. A *pa = new A();
  34. B *pb;
  35. C *pc;
  36.  
  37. //情况①
  38. pb = dynamic_cast<B*>(pa); //向下转型失败
  39. if(pb == NULL){
  40. cout<<"Downcasting failed: A* to B*"<<endl;
  41. }else{
  42. cout<<"Downcasting successfully: A* to B*"<<endl;
  43. pb -> func();
  44. }
  45. pc = dynamic_cast<C*>(pa); //向下转型失败
  46. if(pc == NULL){
  47. cout<<"Downcasting failed: A* to C*"<<endl;
  48. }else{
  49. cout<<"Downcasting successfully: A* to C*"<<endl;
  50. pc -> func();
  51. }
  52.  
  53. cout<<"-------------------------"<<endl;
  54.  
  55. //情况②
  56. pa = new D(); //向上转型都是允许的
  57. pb = dynamic_cast<B*>(pa); //向下转型成功
  58. if(pb == NULL){
  59. cout<<"Downcasting failed: A* to B*"<<endl;
  60. }else{
  61. cout<<"Downcasting successfully: A* to B*"<<endl;
  62. pb -> func();
  63. }
  64. pc = dynamic_cast<C*>(pa); //向下转型成功
  65. if(pc == NULL){
  66. cout<<"Downcasting failed: A* to C*"<<endl;
  67. }else{
  68. cout<<"Downcasting successfully: A* to C*"<<endl;
  69. pc -> func();
  70. }
  71.  
  72. return ;
  73. }

运行结果:

Downcasting failed: A* to B*
Downcasting failed: A* to C*
-------------------------
Downcasting successfully: A* to B*
Class D
Downcasting successfully: A* to C*
Class D

C++语言基础(24)-四种类型转换运算符(static_cast、dynamic_cast、const_cast和reinterpret_cast)的更多相关文章

  1. C++中的四种类型转换运算符static_cast、dynamic_cast、const_cast和reinterpret_cast的使用

    1.上一遍讲述了C语言的隐式类型转换和显示类型转换,C语言之所以增加强制类型转换,就是为了强调转换的风险性,但这种强调风险的方式是比较粗放了,粒度比较大,它并没有表明存在什么风险,风险程度如何. 2. ...

  2. 引用、数组引用与指针引用、内联函数inline、四种类型转换运算符

    一.引用 (1).引用是给一个变量起别名 定义引用的一般格式:类型  &引用名 = 变量名: 例如:int a=1;  int  &b=a;// b是a的别名,因此a和b是同一个单元 ...

  3. 从零开始学C++之从C到C++(二):引用、内联函数inline、四种类型转换运算符

    一.引用 (1).引用是给一个变量起别名 定义引用的一般格式:类型  &引用名 = 变量名: 例如:int a=1; int  &b=a;// b是a的别名,因此a和b是同一个单元 注 ...

  4. C++语言中的四种类型转换

    1 引子 这篇笔记是根据StackOverflow上面的一个问题整理而成,主要内容是对C/C++当中四种类型转换操作进行举例说明.在之前其实对它们都是有所了解的,而随着自己在进行总结,并敲了一些测试示 ...

  5. C++中四种类型转换以及const_cast是否能改变常量的问题

    we have four specific casting operators:dynamic_cast, reinterpret_cast, static_cast and const_cast. ...

  6. [转]C++中四种类型转换符的总结

    C++中四种类型转换符的总结 一.reinterpret_cast用法:reinpreter_cast<type-id> (expression)    reinterpret_cast操 ...

  7. C++ 四种类型转换

    在写代码中经常会有很多的隐式类型转换或显式类型转换. 对于隐式的类型转换主要是放生在赋值的时候,讲变量赋值给不同类型的变量的时候就会发生类型转换,如果是宽化转换(即从占字节少的类型向占字节多的类型转换 ...

  8. c++ --> c++中四种类型转换方式

    c++中四种类型转换方式   c风格转换的格式很简单(TYPE)EXPRESSION,但是c风格的类型转换有不少缺点, 1)它可以在任意类型之间转换,比如你可以把一个指向const对象的指针转换成指向 ...

  9. 【C++】类型转换简述:四种类型转换方式的说明及应用

    本文主要简述在C++中四种类型转换的方式:static_cast.reniterpret_cast.const_cast和dynamic_cast. 在介绍C++类型转换方式之前,我们先来看看C语言的 ...

随机推荐

  1. FORM-加载前指定日期时间格式

    PRE-FORM -- Standard date format --BEGIN  set_application_property(DATE_FORMAT_COMPATIBILITY_MODE, ' ...

  2. Linux/Unix C编程之的perror函数,strerror函数,errno

    #include <stdio.h> // void perror(const char *msg); #include <string.h> // char *strerro ...

  3. AI 语音对话技术

    机器学习以及自然语言处理技术的进步,开启了人与人工智能进行语音交互的可能,人们透过对话的方式获取信息.与机器进行交互,将不再只是存在科幻情结当中.语音交互是未来的方向,而智能音箱则是语音交互落地的第一 ...

  4. C语言i++和++i的区别和指针*(a++)和*(++a)的区别

    i++ :先引用后增加++i :先增加后引用i++ :先在i所在的表达式中使用i的当前值,后让i加1 ++i :让i先加1,然后在i所在的表达式中使用i的新值 一.c语言中i++和++i的运行效果是不 ...

  5. Indirect Buffers

    间接cmd 用在 gpu建立的cmd 不需要cpu参与 用indirect cpu gpu就不会互相等待了 直接gpu建立了 gpu用 之前的cmd是cpu建立 填入数据 gpu拿来执行的 在meta ...

  6. 可视化Tensorboard图中的符号意义

    可视化Tensorboard图中的符号意义

  7. R简易安装

    post={"title":"my Blog post","content":"Here's my blog post" ...

  8. 使用jstack和TDA进行java线程dump分析

    转载:http://blog.csdn.net/everlasting_188/article/details/51943095 1.jstack重点关注 命令行:jstack [-l][F] pid ...

  9. Junit测试Spring应用Dubbo测试框架之-Excel 工具类

    package com.tree.autotest.demo; import com.alibaba.fastjson.JSON;import org.apache.poi.hssf.usermode ...

  10. Java读写二进制文件示例

    相对于文本文件,二进制文件读写快,定位快而准,下面是代码示例: import java.io.DataInput; import java.io.DataOutput; import java.io. ...