reinterpret_cast static_ca..
时间:2010-10-12 来源:gxxliu
reinterpret_cast允许任何类型的指针转换到别的任何类型的指针,不太安全,要小心使用。
#include <iostream>
unsigned short Hash(void *p)
//Returns a hash code based on an address
{
unsigned int val = reinterpret_cast<unsigned int>(p);
return (unsigned short)(val ^ (val >> 16));
}
using namespace std;
int main()
{
int a[20];
for(int i = 0; i < 20; i++)
cout << Hash(a + i) << endl;
}
static_cast是静态的,没有运行时的类型检查,而dynamic_cast有运行时的类型检查,static_cast不安全,一般少用,用的时候自己必须想清楚是否安全!这两个主要是对对象指针和引用的转换
class B{ ...};
class D : public B{ ... };
void f(B* pb, D* pd)
{
D* pd2 = static_cast<D*>(pb); // not safe, pb may
//point to just B
B* pb2 = static_cast<B*>(pd); // safe conversion
...
} static_cast
用于数字之间的转换,如int a = static_cast<int>(0.5f);等
用于类层次之间的转换,即只能用于从父类指针向子类指针转换,不可在同一继承层次中的类的指针之间互相转换。
static_cast是静态转换,编译时刻进行转换,并进行正确的对象布局(比如虚函数表的位置)。比如CC派生自CA和CB,而如下:
CC c; CA *pA = static_cast<CA*>(&c);则正确,而
CA *pA = reinterpret_cast<CA*>(&c);不一定正确,要视CC定义时,CA和CB之间的顺序。
假定c对象中,开头8个字节是CB的部分,接着8个字节是CA的部分,最后8个字节是CC自己增加的部分,而用static_cast就会将&c返回的4个字节长度的数加个8,即正确的类型转换(编译时刻完成),但是reinterpret_cast就不会加8。
reinterpret_cast是强制转换,即将被转换的对象看作一个数字(小于等于4字节),不论其是否指针,即可如下:
CC *pC = reinterpret_cast<CC*>(1.0f);
不会象static_cast那样检测类型,判断两边是否属于同一个继承层次,并进行相应的指针偏移(如上就必须偏移8字节)。
dynamic_cast和static_cast相同,会进行指针的偏移,不过是运行时进行转换,就可检测被转换对象到底是否在同一个继承层次,不是象static_cast那样通过程序员的声明来确定,而是通过被转换对象所带有的运行时期类信息(RTTI)确定,如果不是,将返回null以指出失败。
由于需要RTTI的支持,因此每个对象将会比原来的尺寸多出4个字节用来存放RTTI,将会增加内存的损耗;并且要进行条件判断,速度将会更慢。要支持RTTI,需要开启相应的编译器选项。
一般应不使用dynamic_cast,且不开启RTTI,除非程序必需要用到RTTI进行运行时期信息识别,但这种情况一般都可使用其他方式实现,避开RTTI的使用。
const_cast完全是出于语意的需求,只是简单的将const的变量转成非const或反之,由于是针对语意的,说起来比较麻烦,在此不表。
应该全部使用上诉4个C++提供的转换符,而不要使用C语言风格转换符(对于函数指针则只有用C语言转换符)。使用C语言风格转换符将会统一使用static_cast,即自动的进行指针的偏移,如果不希望进行偏移,还得((CA*) ((int*)&c ) )。并且编译时,新的转换符意义明确,可以加快编译器的编译(不用去判断是否在同一个继承层次,虽然加快的速度人是不可能感觉得出来的),而且使用新的转换符,程序的可读性增加,并且const_cast的加入更增加了语意的完善。
#include <iostream>
unsigned short Hash(void *p)
//Returns a hash code based on an address
{
unsigned int val = reinterpret_cast<unsigned int>(p);
return (unsigned short)(val ^ (val >> 16));
}
using namespace std;
int main()
{
int a[20];
for(int i = 0; i < 20; i++)
cout << Hash(a + i) << endl;
}
static_cast是静态的,没有运行时的类型检查,而dynamic_cast有运行时的类型检查,static_cast不安全,一般少用,用的时候自己必须想清楚是否安全!这两个主要是对对象指针和引用的转换
class B{ ...};
class D : public B{ ... };
void f(B* pb, D* pd)
{
D* pd2 = static_cast<D*>(pb); // not safe, pb may
//point to just B
B* pb2 = static_cast<B*>(pd); // safe conversion
...
} static_cast
用于数字之间的转换,如int a = static_cast<int>(0.5f);等
用于类层次之间的转换,即只能用于从父类指针向子类指针转换,不可在同一继承层次中的类的指针之间互相转换。
static_cast是静态转换,编译时刻进行转换,并进行正确的对象布局(比如虚函数表的位置)。比如CC派生自CA和CB,而如下:
CC c; CA *pA = static_cast<CA*>(&c);则正确,而
CA *pA = reinterpret_cast<CA*>(&c);不一定正确,要视CC定义时,CA和CB之间的顺序。
假定c对象中,开头8个字节是CB的部分,接着8个字节是CA的部分,最后8个字节是CC自己增加的部分,而用static_cast就会将&c返回的4个字节长度的数加个8,即正确的类型转换(编译时刻完成),但是reinterpret_cast就不会加8。
reinterpret_cast是强制转换,即将被转换的对象看作一个数字(小于等于4字节),不论其是否指针,即可如下:
CC *pC = reinterpret_cast<CC*>(1.0f);
不会象static_cast那样检测类型,判断两边是否属于同一个继承层次,并进行相应的指针偏移(如上就必须偏移8字节)。
dynamic_cast和static_cast相同,会进行指针的偏移,不过是运行时进行转换,就可检测被转换对象到底是否在同一个继承层次,不是象static_cast那样通过程序员的声明来确定,而是通过被转换对象所带有的运行时期类信息(RTTI)确定,如果不是,将返回null以指出失败。
由于需要RTTI的支持,因此每个对象将会比原来的尺寸多出4个字节用来存放RTTI,将会增加内存的损耗;并且要进行条件判断,速度将会更慢。要支持RTTI,需要开启相应的编译器选项。
一般应不使用dynamic_cast,且不开启RTTI,除非程序必需要用到RTTI进行运行时期信息识别,但这种情况一般都可使用其他方式实现,避开RTTI的使用。
const_cast完全是出于语意的需求,只是简单的将const的变量转成非const或反之,由于是针对语意的,说起来比较麻烦,在此不表。
应该全部使用上诉4个C++提供的转换符,而不要使用C语言风格转换符(对于函数指针则只有用C语言转换符)。使用C语言风格转换符将会统一使用static_cast,即自动的进行指针的偏移,如果不希望进行偏移,还得((CA*) ((int*)&c ) )。并且编译时,新的转换符意义明确,可以加快编译器的编译(不用去判断是否在同一个继承层次,虽然加快的速度人是不可能感觉得出来的),而且使用新的转换符,程序的可读性增加,并且const_cast的加入更增加了语意的完善。
相关阅读 更多 +