C++中有四种强制类型转换: 静态转换:static_cast、动态转换:dynamic_cast、重新解释:reinterpret_cast、常量转换(去常性):const_cast
1.静态转换(static_cast):可以用于基本数据类型之间的转换,也可以将基类指针或引用转换为派生类指针或引用,但是转换时需要保证类型转换是安全的。静态转换不能用于去除对象的const、volatile属性。
2.动态转换(dynamic_cast):主要用于将基类指针或引用转换为派生类指针或引用,但是转换时需要判断类型转换是否安全,如果不安全则返回空指针。只有指向具有多态性质的类的基类指针或引用才能使用dynamic_cast。
3.重新解释转换(reinterpret_cast):将一个指针或引用转换为一个与其类型无关的指针或引用。这种转换不会进行类型检查,因此很容易引发未定义的行为,应该避免使用。
4.常量转换(const_cast):用于去除一个变量或指针的const、volatile属性。这种转换也需要谨慎使用,因为去除const属性可能会导致未定义的行为。
static_cast
static_cast<目的类型>(表达式)
1.基本数据类型之间的转换
{
int a = 5;
float b = 2.2;
//printf("%f\n", a);//错误输出
//printf("%d\n", b);//错误输出
printf("%f\n", (float)a);
printf("%d\n", (int)b);
a = static_cast<int>(b);//c++的强转
}
2.枚举类型之间的转换
int main()
{
enum AA{A = 3,B = 10};
enum BB{C = 5,D = 30};
int a = 20;
enum AA aa = A;
cout << aa << endl;
//aa = a;//枚举类型的只能用枚举类型内的赋值
aa = static_cast<enum AA>(a);
cout << aa << endl;
enum BB bb = C;
aa = static_cast<enum AA>(bb);
}
3.指针类型转换成void*
int main()
{
int a = 10;
int* p = nullptr;
char ch = 'a';
void* vp = &a;
p = static_cast<int*>(vp);
cout << *p << endl;
//不安全--两边解析的大小不同
vp = &ch;
p = static_cast<int*>(vp);
cout << *p << endl;
}
4.将一个变量转换成常量
这种不用强转其实也可以
int main()
{
int a = 20;
const int ca = a;
const int cb = static_cast<const int>(a);
cout << ca << endl;
}
5.基类和派生类之间的转换--没有virtual
class A
{
public:
void fn() { cout << "A::fn" << endl; }
void gn() { cout << "A::gn" << endl; }
};
class B :public A
{
public:
void fn() { cout << "B::fn" << endl; }//隐藏,没有虚
void hn() { cout << "B::hn" << endl; }
};
int main()
{
A a;
B b;
A* pa = &b;
pa->fn();//A
pa->gn();//A
// B* pb = &a;//error
B* pb = static_cast<B*>(&a);
pb->fn();//B
pb->gn();//A
pb->hn();//B
pb->A::fn();//A
}
6.没有关系的类之间的转换
class A
{
public:
void fn() { cout << "A::fn" << endl; }
};
class B
{
public:
B(A&a){}//构造函数可以进行强转
void gn() { cout << "B::gn" << endl; }
};
int main()
{
A a;
B b = static_cast<B>(a);//B b(a);
b.gn();
}
dynamic_cast
将基类的指针或引用安全的转换为派生类的指针或引用,并用派生类的指针或引用来调用非虚函数。
注意:当使用dynamic_cast时,该类型要包含有虚函数,才能进行转换,否则错误。
class A
{
public:
void print() { cout << "A::print" << endl; }
virtual ~A() {};//多态
};
class B :public A
{
public:
void show()
{
cout << "B::show" << endl;
}
};
int main()
{
A* pa = new A;
B* pb = dynamic_cast<B*>(pa);
pb->print();
pb->show();
}
reinterpret_cast
适用于指针转换为另一种指针,转化不用修改指针变量值数据存储格式,不改变指针变量的值,只需要在编译时重新解释指针的类型即可。也可以将指针,直接转化成整形值。
int main1()
{
float ff = 3.5f;
float* pf = &ff;
int* pi = reinterpret_cast<int*>(pf);//编译时重新解释
cout << *pi << endl;//取不到正确的值
cout << *pf << endl;//pf不变
//整形按二进制补码存
unsigned int a = -2;//把-2放到a开辟的空间中
/*
00000000 00000000 00000000 00000010
11111111 11111111 11111111 11111110:-2,4294967294
unsigned无符号位
*/
//浮点sem存
}
class A
{
};
class B
{
};
int main()
{
A* pa = new A;
B* pb = reinterpret_cast<B*>(pa);
//B*pb = (B*)pa;
int a = 10;
int* pi = &a;
long j = reinterpret_cast<long>(pi);
cout << j << endl;//地址值
}
const_cast
static_cast不能移除变量的const属性,const_cast可以,但是就算可以强转了const在数据区的内容也不改变。
int main()
{
const int cb = 10;
//int* p = &cb;
//int* p = static_cast<int*>(&cb);//error
int* p = const_cast<int*>(&cb);//
*p = 30;
cout << cb << endl;//cb在字符串常量区,改不了,输出10
}