reinterpret_cast and const_cast

reinterpret_cast

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++对象模型简介]

【在C++中,涉及相关指针的强制类型转换,并不是不改变指针值,有时(涉及多重继承时)会根据需要改变底层值。reinterpret_cast才是只改变解释方式,不改变底层值。】

【注意】C++中的隐式类型转换的方式和static_cast的转换行为类似。(只是static_cast对于不相关指针的转换无能为力)

时间: 2024-10-20 21:07:53

reinterpret_cast and const_cast的相关文章

C++类型转换运算符 static_cast,dynamic_cast,reinterpret_cast,const_cast

类型转换是一种让程序猿可以临时或永久性改变编译器对对象的解释机制.可改变对象解释方式的运算符称为类型转换运算符. 为何须要进行类型转换 通常为了实现使用不同环境的个人和厂商编写的模块可以相互调用和协作,程序猿须要让编译器依照所需的方式解释数据,并成功编译和运行.一个非常经典的样例是:眼下非常多C++程序依旧在使用非常多年前用C编写的库.而针对这些C语言编译器编写的库必须依赖整形来保存布尔值,因此对于这些编译器来说.bool类型的定义就类似于: typedef unsigned short BOO

C++的类型转换:static_cast、dynamic_cast、reinterpret_cast和const_cast(dynamic_cast还支持交叉转换,const_cast将一个类的const、volatile以及__unaligned属性去掉)

在C++中,存在类型转换,通常意味着存在缺陷(并非绝对).所以,对于类型转换,有如下几个原则:(1)尽量避免类型转换,包括隐式的类型转换(2)如果需要类型转换,尽量使用显式的类型转换,在编译期间转换(3)避免使用reinterpret_cast和老式的强制类型转换操作符通常,隐式的类型转换会导致警告,需要重视这些警告,并使用显式的类型转换代替,例如static_cast代替一些算术类型转换. 在C++中,对象的类型通常有如下几种:(一)内置类型,如int ,bool ,枚举类型等(二)自定义类型

C++的类型转换:static_cast、dynamic_cast、reinterpret_cast和const_cast

在C++中,存在类型转换,通常意味着存在缺陷(并非绝对).所以,对于类型转换,有如下几个原则:(1)尽量避免类型转换,包括隐式的类型转换(2)如果需要类型转换,尽量使用显式的类型转换,在编译期间转换(3)避免使用reinterpret_cast和老式的强制类型转换操作符通常,隐式的类型转换会导致警告,需要重视这些警告,并使用显式的类型转换代替,例如static_cast代替一些算术类型转换. 在C++中,对象的类型通常有如下几种:(一)内置类型,如int ,bool ,枚举类型等(二)自定义类型

C++类型转化:static_cast,reinterpret_cast,dynamic_cast,const_cast

类型转换名称和语法 C风格的强制类型转换(Type Cast)很简单,不管什么类型的转换统统是: TYPE b = (TYPE)a C++风格的类型转换提供了4种类型转换操作符来应对不同场合的应用. static_cast 静态类型转换.如int转换成char reinterpreter_cast 重新解释类型 dynamic_cast 命名上理解是动态类型转换.如子类和父类之间的多态类型转换. const_cast, 字面上理解就是去const属性. 4种类型转换的格式: TYPE B = s

C++ ------ static_cast,dynamic_cast,reinterpret_cast,const_cast

C++类型转换分为:隐式类型转换和显式类型转换 第1部分. 隐式类型转换 又称为"标准转换",包括以下几种情况:1) 算术转换(Arithmetic conversion) : 在混合类型的算术表达式中, 最宽的数据类型成为目标转换类型. int ival = 3; double dval = 3.14159; ival + dval;//ival被提升为double类型 2)一种类型表达式赋值给另一种类型的对象:目标类型是被赋值对象的类型 int *pi = 0; // 0被转化为i

C++中static_cast/const_cast/dynamic_cast/reinterpret_cast的区别和使用

C风格的强制转换较简单,如将float a转换为int b,则可以这样:b = (int)a,或者b=int(a). C++类型转换分为隐式类型转换和显示类型转换. 隐式类型转换又称为标准转换,包括以下几种情况: (1).算术转换:在混合类型的算术表达式中,最宽的数据类型成为目标转换类型: (2).一种类型表达式赋值给另一种类型的对象:目标类型是被赋值对象的类型: (3).将一个表达式作为实参传递给函数调用,此时形参和实参类型不一致:目标转换类型为形参的类型: (4).从一个函数返回一个表达式,

staitc_cast,const_cast....

#include <iostream> using namespace std; int main() { //1.const_cast //const int a = 10; //int* ptr = const_cast<int*>(&a);//将const属性去除 //*ptr = 100; //2.static_cast //编译器隐式执行的操作都可以由static_cast显示完成,显示的强制类型转换会产生警告,当使用static_cast会关闭警告 //stat

C++ 强制转换

C++中有两种风格的类型转换,一种C风格的,一种C++风格的.C风格:int a = int(2.33); C++新增了四种cast运算符,static_cast<type>(var), const_cast<tyep>(var), reinterpret_cast<type>(var), dynamic_cast<type>(var)static_cast<type>(var)用来替换C风格的类型转换.比如上面的转换可以写成:int a = s

C++中“强制转换”的四大天王

哈哈,这个标题有点搞笑了!笑一笑,十年少,希望大家都嗨心! 在C++中主要有四种强制类型转换:static_cast,reinterpret_cast,const_cast,dynamic_cast. 1)static_cast<T*>(a) 将地址a转换成类型T,T和a必须是指针.引用.基本数据类型或枚举类型.在运行时转换过程中,不进行类型检查来确保转换的安全性. class B { ... }; class D : public B { ... }; void f(B* pb, D* pd