const_cast
const_cast用于修改类型的const、volatile属性。
const_cast<?>(?), <>中必须是指针、引用或者右值 - (the type in a const_cast must be a pointer, reference, or pointer to member to an object type)。
class B
{
public:
int _m;
B() :_m(100){};
};
int test_cast()
{
const B b1;
B* b2 = const_cast<B*>(&b1);
b2->_m = 1;
cout << &(b1._m) << endl;
cout << &b2->_m << endl;
cout << b1._m << endl;
cout << b2->_m << endl;
const int i = 100;
int* ii = const_cast<int*>(&i);
*ii = 1;
cout << &i << endl;
cout << ii << endl;
cout << i << endl;
cout << *ii << endl;
return 0;
}
output:
addr of b1._m: 0000005A90EFF8D0
addr of b2._m: 0000005A90EFF8D0
value of b1._m: 1
value of b2._m: 1
addr of i: 0000005A90EFF8D4
addr of ii: 0000005A90EFF8D4
value of i: 100
value of ii: 1
可以通过const_cast修改const B b1中的成员变量的值。但要注意的是const int通过const_cast修改值之后,很神奇的,原值i和修改值ii的地址是一样的,但是其值是不一样的。
reinterpret_cast
强制类型转换符,任意转换,使用需谨慎。
用于进行各种不同类型的指针之间、不同类型的引用之间以及指针和能容纳指针的整数类型之间的转换。转换时,执行的是逐个比特复制的操作。
int *n = new int;
double *d = reinterpret_cast<double*>(n);
有意义的用法是hash函数中。
// 将地址转化为hash值
unsigned short Hash( void *p ) {
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把一个表达式转换为某种类型,但没有运行时类型检查来保证转换的安全性。不能用于在不同类型的指针之间互相转换,也不能用于整型和指针之间的互相转换,当然也不能用于不同类型的引用之间的转换;能用于整型和浮点型、字符型之间的互相转换,以及类的上行转换。
double n = 100.092;
int d = static_cast<int>(n); // d=100
// error
int *d = static_cast<int*>(&n);
dynamic_cast将一个基类对象指针(或引用)转换到继承类指针,与static_cast不同的是dynamic_cast会根据基类指针是否真正指向继承类指针来做相应处理。
dynamic_cast<?>(?), <>中必须是指针、引用或者void *- (the type in a dynamic_cast must be a pointer or reference to a complete class type, or void *)
class B
{
public:
int m_iNum;
virtual void foo();
};
class D : public B
{
public:
char *m_szName[100];
};
void func(B* pb)
{
D* pd1=static_cast<D*>(pb);
D* pd2=dynamic_cast<D*>(pb);
}
上行转换时安全的,即D->B。如果pb是D类型,则pd1和pd2是一样的,且都可以安全执行操作;
下行转换,即B->D会出现问题,static_cast的问题是转换后的pd1是一个B类型的指针,若有对m_szName的操作则会出现问题;而dynamic_cast将会返回空指针,即pd2为空指针,因为pd2本身是从B转换而来,无法变为D,所以可以尽早防止error产生。
另外要注意:B 要有虚函数,否则会编译出错;static_cast则没有这个限制。