reinterpret_cast

来源:互联网 发布:淘宝一元抢拍是真的吗 编辑:程序博客网 时间:2024/05/18 01:03

reinterpret_cast的原型为:reinterpret_cast<typeid> (expression).type_id必须是一个指针,引用,算术类型,函数指针,成员指针等。它可以把一个整型转换为指针,也可以把一个指针转换为整型。总结来说,reinterpret_cast可以允许任何指针类型(引用)之间的转换,整型与指针类型间的转换以及指针与足够大的整型之间的转换。

reinterpret_cast转换的实质是让编译器重新给出对象的比例模型而不进行二值转换。也就是让编译器按照目标转换类型在内存中所占的比特位重新编译原始数据类型。转换前后对象的地址值是不变的,只是对象的读取内存的比例变了而已。

虽然reinterpret_cast有很强的转换功能,但是不能乱用。IBM的C++指南、C++之父Bjarne Stroustrup的FAQ网页MSDN的Visual C++也都指出:错误的使用reinterpret_cast很容易导致程序的不安全,只有将转换后的类型值转换回到其原始类型,这样才是正确使用reinterpret_cast方式。比如下面的代码:

typedef int (*FunctionPointer)(int); 
int value = 21; 
FunctionPointer funcP; 
funcP = reinterpret_cast<FunctionPointer> (&value); 
funcP(value);

在这里我们定义一个函数指针,参数类型为int,返回值类型为int。我们讲一个int型数据的地址值赋给函数指针,然后将int型数据作为参数传递给函数。这段代码虽然可以编译通过,但是会得到"EXC_BAD_ACCESS"的运行错误,因为我们通过funcP所指的地址找到的并不是函数入口。

// ConsoleApplication29.cpp : 定义控制台应用程序的入口点。//#include "stdafx.h"#include<iostream>#include<string>using namespace std;class CBaseX{public:int x;CBaseX() { x = 10; cout <<"CBaseX() " << endl;}void foo() { printf("CBaseX::foo() x=%d/n", x); }};class CBaseY{public:int y;int *py;CBaseY() { y = 16; py = &y;cout <<"CBaseY() " << endl;}void bar() {cout << y << endl;cout << py<< endl;//printf("CBaseY::bar() y=%d, *py=%d/n", y, *py);}};class CDerived : public CBaseX, public CBaseY{public:int z;}; //情况1:两个无关的类之间的转换int _tmain(int argc, _TCHAR* argv[]){   int n = 9;    double d =reinterpret_cast<double&>(n);cout << d << endl;CBaseY* pY3 = new CBaseY();printf("CBaseY* pY3 = %d/n", (int)pY3);CDerived* pD3 = reinterpret_cast<CDerived*>(pY3);printf("CDerived* pD3 = %d/n", (int)pD3);cout << pD3->y <<" "<<pD3->py<<" "<<pD3->z<< endl;system("pause");return 0;}

在以上例子中,将int型的n转换为double型,由于int型数据类型在内存中占4个字节,而double型数据类型在内存中占8个字节,因此使用reinterpret_cast进行转换时,编译器在原对象地址处读取8字节内容,多读了4字节。

而在将py3转换为pd3的过程中,编译器将按照CDerived占用内存的比例模型重新读取py3中的内容。因此编译器会将Py3中的y认为是pd3中的x,py3中的py当成是pd3中的y。


0 0