reinterpret
reinterpret意为“重新解释”
reinterpret_cast是C++中与C风格类型转换最接近的类型转换运算符。它让程序员能够将一种对象类型转换为另一种,不管它们是否相关。
reinterpret_cast用在任意指针(或引用)类型之间的转换;以及指针与足够大的整数类型之间的转换;从整数类型(包括枚举类型)到指针类型,无视大小。
(所谓"足够大的整数类型",取决于操作系统的参数,如果是32位的操作系统,就需要整形(int)以上的;如果是64位的操作系统,则至少需要长整形(long)。具体大小可以通过sizeof运算符来查看)。
【注意】reinterpret_cast不能用于内置类型之间的转换,只能用于不同指针之间的转换。
CBase* pBase = new CBase( ) ;
CDerived* pDerived = reinterpret_cast<CDerived*>(pBase) ;
这种类型转换实际上是强制编译器接受static_cast通常不允许的类型转换,它并没有改变指针值的二进制表示,只是改变了编译器对源对象的解释方式。
【应尽量避免使用reinterpret_cast】
reinterpret_cast VS static_cast
static_cast主要管:有继承关系类的指针和内置数据类型的转换(和C的内置类型转换规则一致,可能改变底层的位,也可能不改变)。
reinterpret_cast主要管:所有指针(引用)之间的转换
在它们管理的交叉点处——有继承关系的指针的转换,处理方式有所不同。
static_cast和reinterpret_cast的区别主要在于多重继承

class A
{
public:
int m_a;
};
class B
{
public:
int m_b;
};
class C : public A, public B {}; 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 VS const_cast
reinterpret_cast不能像const_cast那样去除const修饰符。

int main()
{
typedef void (*FunctionPointer)(int);
int value = 21;
const int* pointer = &value; int * pointer_r = reinterpret_cast<int*> (pointer); //编译报错 FunctionPointer funcP = reinterpret_cast<FunctionPointer> (pointer);
}

reinterpret_cast只能改变指针(或引用)的解释方式,不能把其上的const锁转换掉。
const_cast
const_cast让程序员能够关闭对象的访问修饰符const。
在理想的情况下,程序员将经常在正确的地方使用关键字const。
但是现实世界,经常可以看到该使用const的地方没有使用。
这样,在外部函数中调用类中的这些成员函数,可能会报错。

CSomeClass
{
public:
….
void DisplayMember( ) ;
};
void DisplayAllData( const CSomeClass& mData )
{
mData.DisplayMembers ( ) ; //编译报错
}

为什么会编译报错?
因为DisplayMembers为普通的成员函数,故DisplayMembers成员函数中隐藏的this指针,会被编译器设置为CSomeClass* this。而mData是被const修饰的,mData.DisplayMembers ( ) ;即是DisplayMembers ( &mData); 这样,实参和形参类型不一致,编译器会报错。
如何修改这一问题?
①把函数列表上mData前的const去掉。
这样,使代码的安全性降低,其后的代码可能会修改mData中的值。
②在成员函数DisplayMembers前添上const。
这样固然最好,但是如果CSomeClass是第三方的类,我们没有其源代码,那怎么办?
③使用const_cast把mData上的const锁暂时去掉。
void DisplayAllData( const CSomeClass& mData )
{
CSomeClass& refData = const_cast< CSomeClass &>(mData) ;
refData.DisplayMembers ( ) ;
}
另外:const_cast也可用于指针。
void DisplayAllData( const CSomeClass* pData )
{
CSomeClass* pCastedData = const_cast< CSomeClass *>( pData) ;
pCastedData ->DisplayMembers ( ) ;
}
C++类型转换符存在的问题:
static_cast的用途可用C风格类型转换进行处理,且更简单。
例:
double dPi = 3.14 ;
int num1 = static_cast<int>(dPi) ;
int num2 = (int)dPi ; CDerived* pDerived1 = static_cast<CDerived*>(pBase) ;
CDerived* pDerived2 = (CDerived*)pBase ;
故,Bjarne Stroustrup说:“由于static_cast如此拙劣且难以输入,因此您在使用它之前很可能会三思。这很不错,因为类型转换在现代C++中是最容易避免的。”
因此,在现代C++中,除dynamic_cast外的类型转换都是可以避免的。
仅当需要满足遗留应用程序需求时,才需要使用其它类型转换运算符。在这种情况下,程序员通常倾向于使用C风格类型转换而不是使用C++类型转换运算符。
重要的是,应尽量避免使用类型转换,而一旦使用类型转换,务必要知道幕后发生的情况。
关于隐式转换:
例:

#include <iostream> using namespace std ; class A
{
int m_nA ;
};
class B
{
int m_nB;
};
class C : public A, public B
{
int m_nC;
}; int main(void)
{
C* pC = new C ;
B* pB = dynamic_cast<B*>(pC) ;
A* pA = dynamic_cast<A*>(pC) ; if ( pC==pB )
cout << “equal” << endl ;
else
cout << “not equal” << endl ; if ( (int)pC == (int)pB )
cout << “equal” <<endl ;
else
cout << “not equal” << endl ; return 0 ;
}
//程序输出如下:
//equal
//not equal

if ( pC == pB )这里两端数据类型不同,比较时需要进行隐式类型转换。( pC == pB )相当于:pC == (C*)pB ;
pB实际上指向的地址是对象C中的子类B的部分,从地址上跟pC不一样,所以直接比较地址数值的时候是不相同的。故 (int)pC 与(int)pB 不同。
但是:(C*)pB相当于static_cast<C*>(pB)
它们计算了父子类指针转换的偏移量,并将之转换到正确的地址(c里面有m_a,m_b,转换为B*指针后指到m_b处)
【在C++中,涉及相关指针的强制类型转换,并不是不改变指针值,有时(涉及多重继承时)会根据需要改变底层值。reinterpret_cast才是只改变解释方式,不改变底层值。】
【注意】C++中的隐式类型转换的方式和static_cast的转换行为类似。(只是static_cast对于不相关指针的转换无能为力)
reinterpret的更多相关文章
- C++四种类型转换方式。
类型转换有c风格的,当然还有c++风格的.c风格的转换的格式很简单(TYPE)EXPRESSION,但是c风格的类型转换有不少的缺点,有的时候用c风格的转换是不合适的,因为它可以在任意类型之间转换,比 ...
- cpp 4个类型转换
static_cast.dynamic_cast.reinterpret_cast.const_cast 之间的区别 static_cast 用法:static_cast (expression) 说 ...
- [翻译]类型双关不好玩:C中使用指针重新解释是坏的
原文地址 Type punning isn't funny: Using pointers to recast in C is bad. C语言中一个重新解释(reinterpret)数据类型的技巧有 ...
- C++学习笔记 四种新式类型转换
static_cast ,dynamic_cast,const_cast,reinterpret_cast static_cast 定义:通俗的说就是静态显式转换,用于基本的数据类型转换,及指针之间的 ...
- Tomcat崩溃
参考: http://bbs.csdn.net/topics/390391810?page=1 自己遇到的: --------------------------------------------- ...
- c++ 数据类型转换: static_cast dynamic_cast reinterpret_cast const_cast
c++ 数据类型转换: static_cast dynamic_cast reinterpret_cast const_cast [版权声明]转载请注明出处 http://www.cnblogs.c ...
- c++面试题
转自http://blog.csdn.net/jingxuewang110/article/details/6789557/ 1.new.delete.malloc.free关系 delete会调用对 ...
- ACE - ACE_Task源码剖析及线程池实现
原文出自http://www.cnblogs.com/binchen-china,禁止转载. 上篇提到用Reactor模式,利用I/O复用,获得Socket数据并且实现I/O层单线程并发,和dispa ...
- C++标准转换运算符
C++类型转换在实际编程中会经常使用,其实,本质上对象的类型用来解释(interpret)对象.因为,每个对象都占据一块内存空间,这块内存空间存放了一段二进制数据.通过标记该对象的类型,告诉如何看待这 ...
随机推荐
- 【Spring】基于@Aspect的AOP配置
Spring AOP面向切面编程,可以用来配置事务.做日志.权限验证.在用户请求时做一些处理等等.用@Aspect做一个切面,就可以直接实现. · 本例演示一个基于@Aspect的小demo 1. ...
- maven 引入的jar有出现两种图标
两种同样都引入到maven项目中,但是第二种在打包的过程中会显示找不到jar,无法调用!
- centos上为新创建的用户(git)指定根目录并生成公钥和私钥
1.修改用户的根目录 vim /etc/passed 2.su git 3.ssh-keygen -t rsa ssh-keygen -t rsa 4.如图所示,如果要实现无密码访问git仓库,把公钥 ...
- Activiti之act_ge_property表引发的坑(dbSchemaUpdate)
Activiti之act_ge_property表引发的坑(dbSchemaUpdate) 参考文档: https://blog.csdn.net/lb19921223/article/details ...
- Cas(04)——更改认证方式
在Cas Server的WEB-INF目录下有一个deployerConfigContext.xml文件,该文件是基于Spring的配置文件,里面存放的内容常常是部署人员需要修改的内容.其中认证方式也 ...
- MultiDesk远程桌面连接
MultiDesk 是一个选项卡(TAB标签)方式的远程桌面连接 (Terminal Services Client),可以管理组远程桌面连接,更改连接端口. 功能特性 绿色软件,只有一个很小的可执行 ...
- Word 查找替换高级玩法系列之 -- 通配符大全A篇
1. 通配符大全一览 序号 特殊字符(不使用通配符) 代码(不使用通配符) 特殊字符(使用通配符) 代码(使用通配符) 1 任意单个字符 ^? 任意单个字符 ? 2 任意数字 ^### 任意数字(单个 ...
- fork() 函数简介
fork() 函数简介 fork系统调用用于创建一个新进程,称为子进程,它与进行fork()调用的进程(父进程)并发运行.创建新的子进程后,两个进程都将执行fork()系统调用之后的下一条指令.子进程 ...
- Python 重点知识整理(基于Python学习手册第四版)
字节型编译 如果Python在系统中有写的权限,当程序运行时Python会把源码编译成字节码(与系统环境无关)存在一个.pyc扩展名文件中,如果没有修改源码而重新运行程序时,不会进行编译的步骤而使用字 ...
- Symmetric Order
#include<stdio.h> int main() { ; ][]; ) { ;i<=n;i++) { scanf("%s",&str[i]); } ...