dynamic_cast在多继承中可以判断无关类之间是否可以转换,例如基类B1和基类B2之间,static_cast可以在隐式转化及其逆转换中进行,但不允许无关类型之间的转换。,dynamic_cast更多是通过rtti信息来判断类型转换的合理性

C++的四个类型转换运算符已经有很久了,但一直没有弄清楚它们的用法,今天看到一本书上的解释,才大致地的了解了其具体的用法.

具体归纳如下:

reinterpret_cast
该函数将一个类型的指针转换为另一个类型的指针.
这种转换不用修改指针变量值存放格式(不改变指针变量值),只需在编译时重新解释指针的类型就可做到.
reinterpret_cast 可以将指针值转换为一个整型数,但不能用于非指针类型的转换.
例:

  1. //基本类型指针的类型转换
  2. double d=9.2;
  3. double* pd = &d;
  4. int *pi = reinterpret_cast<int*>(pd);  //相当于int *pi = (int*)pd;
  5. //不相关的类的指针的类型转换
  6. class A{};
  7. class B{};
  8. A* pa = new A;
  9. B* pb = reinterpret_cast<B*>(pa);   //相当于B* pb = (B*)pa;
  10. //指针转换为整数
  11. long l = reinterpret_cast<long>(pi);   //相当于long l = (long)pi;



const_cast

该函数用于去除指针变量的常量属性,将它转换为一个对应指针类型的普通变量。反过来,也可以将一个非常量的指针变量转换为一个常指针变量。
这种转换是在编译期间做出的类型更改。
例:

  1. const int* pci = 0;
  2. int* pk = const_cast<int*>(pci);  //相当于int* pk = (int*)pci;
  3. const A* pca = new A;
  4. A* pa = const_cast<A*>(pca);     //相当于A* pa = (A*)pca;



出于安全性考虑,const_cast无法将非指针的常量转换为普通变量。

static_cast

该函数主要用于基本类型之间和具有继承关系的类型之间的转换。
这种转换一般会更改变量的内部表示方式,因此,static_cast应用于指针类型转换没有太大意义。
例:

  1. //基本类型转换
  2. int i=0;
  3. double d = static_cast<double>(i);  //相当于 double d = (double)i;
  4. //转换继承类的对象为基类对象
  5. class Base{};
  6. class Derived : public Base{};
  7. Derived d;
  8. Base b = static_cast<Base>(d);     //相当于 Base b = (Base)d;



dynamic_cast

它与static_cast相对,是动态转换。
这种转换是在运行时进行转换分析的,并非在编译时进行,明显区别于上面三个类型转换操作。
该函数只能在继承类对象的指针之间或引用之间进行类型转换。进行转换时,会根据当前运行时类型信息,判断类型对象之间的转换是否合法。dynamic_cast的指针转换失败,可通过是否为null检测,引用转换失败则抛出一个bad_cast异常。
例:

  1. class Base{};
  2. class Derived : public Base{};
  3. //派生类指针转换为基类指针
  4. Derived *pd = new Derived;
  5. Base *pb = dynamic_cast<Base*>(pd);
  6. if (!pb)
  7. cout << "类型转换失败" << endl;
  8. //没有继承关系,但被转换类有虚函数
  9. class A(virtual ~A();)   //有虚函数
  10. class B{}:
  11. A* pa = new A;
  12. B* pb  = dynamic_cast<B*>(pa);



如果对无继承关系或者没有虚函数的对象指针进行转换、基本类型指针转换以及基类指针转换为派生类指针,都不能通过编译。

reinterpret_cast补充

该运算符的用法比较多。
操作符修改了操作数类型,但仅仅是重新解释了给出的对象的比特模型而没有进行二进制转换
例如:int *n= new int ;
double *d=reinterpret_cast<double*> (n);
在进行计算以后, d 包含无用值. 这是因为 reinterpret_cast 仅仅是复制 n 的比特位到 d, 没有进行必要的分析。
因此, 需要谨慎使用 reinterpret_cast.
static_cast 与 reinterpret_cast
reinterpret_cast是为了映射到一个完全不同类型的意思,这个关键词在我们需要把类型映射回原有类型时用到它。我们映射到的类型仅仅是为了故弄玄虚和其他目的,这是所有映射中最危险的。(这句话是C++编程思想中的原话)
static_cast和reinterpret_cast的区别主要在于多重继承,比如
1
2
3
4
5
6
7
8
9
10
11
class A {
    public:
    int m_a;
};
 
class B {
    public:
    int m_b;
};
 
class C : public A, public B {};
那么对于以下代码:
1
2
C c;
printf("%p, %p, %p", &c, reinterpret_cast<B*>(&c), static_cast <B*>(&c));
前两个的输出值是相同的,最后一个则会在原基础上偏移4个字节,这是因为static_cast计算了父子类指针转换的偏移量,并将之转换到正确的地址(c里面有m_a,m_b,转换为B*指针后指到m_b处),而reinterpret_cast却不会做这一层转换。
因此, 你需要谨慎使用 reinterpret_cast.
 

C++类型转化的更多相关文章

  1. Spring mvc @initBinder 类型转化器的使用

    一.单日期格式 因为是用注解完完成的后台访问,所以必须在大配置中配置包扫描器: 1.applicactionContext.xml <?xml version="1.0" e ...

  2. C#定义类型转化 及 格式化字符串

    operator 关键字 operator 关键字用来重载内置运算符,或提供类/结构声明中的用户定义转换.它可以定义不同类型之间采用何种转化方式和转化的结果. operator用于定义类型转化时可采用 ...

  3. C++中的显式类型转化

    类型转化也许大家并不陌生,int i; float j; j = (float)i; i = (int)j; 像这样的显式转化其实很常见,强制类型转换可能会丢失部分数据,所以如果不加(int)做强制转 ...

  4. jQuery源码分析系列(36) : Ajax - 类型转化器

    什么是类型转化器? jQuery支持不同格式的数据返回形式,比如dataType为 xml, json,jsonp,script, or html 但是浏览器的XMLHttpRequest对象对数据的 ...

  5. Asp.net 面向接口可扩展框架之使用“类型转化基础服务”测试四种Mapper(AutoMapper、EmitMapper、NLiteMapper及TinyMapper)

    Asp.net 面向接口可扩展框架的“类型转化基础服务”是我认为除了“核心容器”之外最为重要的组成部分 但是前面博文一出,争议很多,为此我再写一篇类型转化基础服务和各种Mapper结合的例子,顺便对各 ...

  6. Asp.net 面向接口可扩展框架之类型转化基础服务

    新框架正在逐步完善,可喜可贺的是基础服务部分初具模样了,给大家分享一下 由于基础服务涉及面太广,也没开发完,这篇只介绍其中的类型转化部分,命名为类型转化基础服务,其实就是基础服务模块的类型转化子模块 ...

  7. 《精通C#》自定义类型转化-扩展方法-匿名类型-指针类型(11.3-11.6)

    1.类型转化在C#中有很多,常用的是int类型转string等,这些都有微软给我们定义好的,我们需要的时候直接调用就是了,这是值类型中的转化,有时候我们还会需要类类型(包括结构struct)的转化,还 ...

  8. java类型转化之SimpleDateFormat-时间转化

    关于Date,时间戳(long),String类型之间的相互转换,主要是用到类SimpleDateFormat. 先介绍SimpleDateFormat类的一些常见格式: 1.参数: code des ...

  9. Javascript基础系列之(三)数据类型 (类型转化)

    所有语言都有类型转化的能力,javascript也不例外,它也为开发者提供了大量的类型转化访法,通过全局函数,可以实现更为复杂的数据类型. var a = 3; var b = a + 3; var ...

  10. delphi 类型转化

    1.typecasting类型强制转化 var B : Boolean; Begin B := Boolean(1); End; 对于对象和接口,采用as操作符进行转化,但要先进行兼容性判断. 2.P ...

随机推荐

  1. [原创]PostgreSQL Plus Advince Server在 HA环境中一对多的Stream Replication配置(二)

    三.配置主机与备机的ssh无密码登录1.主机s1到备机s3的无密码登录a.创建ssh目录[root@s1 ~]# mkdir /opt/PostgresPlus/9.2AS/.sshb.修改ssh目录 ...

  2. DBus通讯

    linux下进程间通信的方式主要有Pipe(管道),FIFO(命名管道),信号,共享内存,消息队列,信号灯等,这些方式各有 各得特点,如管道是linux下命令行中常用的,用于父子进程的通信.但是这些通 ...

  3. (转) java 复制文件,不使用输出流复制,高效率,文件通道的方式复制文件

    public static void fileChannelCopy(File s, File t) { FileInputStream fi = null; FileOutputStream fo ...

  4. cocos2dx中常见的类及类继承关系

    场景:CCScene,继承自CCNode,几乎完全等于CCNode类 CCNode继承自CCObject,CCObject是真正意义上的父类,CCObject又继承自CCCopying类,CCCopy ...

  5. NodeJS -Express 4.0 用include取代partial

    在Express 4.0 下按如下方法设置: (1)运行cmd 输入:npm install express-partials -g (2)下载成功后.在app.js 中引用此插件   var par ...

  6. Java 8 VM GC Tunning Guide Charter 6

    第六章 并行GC The Parallel Collector The parallel collector (also referred to here as the throughput coll ...

  7. Halcon学习笔记之缺陷检测(二)

    例程:detect_indent_fft.hdev 说明:这个程序展示了如何利用快速傅里叶变换(FFT)对塑料制品的表面进行目标(缺陷)的检测,大致分为三步: 首先,我们用高斯滤波器构造一个合适的滤波 ...

  8. 消息传递选择:返回值 or 抛出异常

    1.返回值 bool 不应该用来表示函数是否调用成功,而应该返回业务值,例如 IsExist,HasNext

  9. Codeforces Beta Round #10 D. LCIS

    题目链接: http://www.codeforces.com/contest/10/problem/D D. LCIS time limit per test:1 secondmemory limi ...

  10. Eclipse maven工程 Missing artifact com.sun:tools:jar:1.5.0:system 解决方法

    今天同事在使用eclipse,引入一个新的maven工程时报错:      Missing artifact com.sun:tools:jar:1.6.0:system   这个问题很奇怪,相同的代 ...