一、隐式转换
这里指编译器帮我们完成的转换,例如将一个整形数据赋给浮点型,编译器会自动展开相关方法进行转换。又如我们比较整形数据和浮点型数据,编译器会自动转为浮点型再比较。
我们使用类似的(int)时编译器也会进行相应操作进行转换,不过这是C语言风格的类型转换,它不支持父类指针赋给子类,也不支持毫无关系的两个类型之间的转换(编译器不知道如何转换),以及对const常量去掉限定等。
二、C++的四种转换方式
为了提高代码可读性,并且实现更方便的数据转换,C++定义了四种类型转换,分别为static_cast、dynamic_cast、reinterpret_cast、const_cast。
(1)static_cast
static_cast即静态数据转换,完成与编译阶段,即将一种数据类型转为另一种数据类型。特殊情况为可以将子类指针赋给父类指针,而不可以反过来,如果你学习了类的存储方式(详见C++学习笔记(3)-多态的实现-CSDN博客)就会知道子类指针赋给父类即将子类指针加上其父类虚表指针的类内偏移。此外,对于一个不相关的类,你可以重载构造函数来实现。
#include <iostream>
using namespace std;
class A{
public:
char a;
A(int a):a(a){
}
};
class B:public A{
public:
char b;
B(int b):A(b),b(b){
}
};
//int A::b = 0;
int main(){
B b(2);
A* a = static_cast<A*>(&b);//子类指针赋给父类
A a2 = static_cast<A>(1);//调用类的构造函数
}
(2)dynamic_cast
代表进行动态类型转换,当父类指针赋给子类时,如果父类指针实际上保存的是父类,及实际上的赋值为父类对象交由子类对象处理,那么会返回NULL,如果源指针为NULL时同样会返回NULL。
需要注意的是,进行dynamic转换必须是实现多态的类的指针,否则编译不通过。
(3)reinterpret_cast
重解释转换,即将数据重新解释为另一种数据,不会对数据本身进行转换,通常用于指针的转换,不会考虑两种类型间有没有关系。
#include <iostream>
using namespace std;
class A{
public:
char a;
A(int a):a(a){
}
void func(){
cout<<"A:"<<a;
}
};
class B{
public:
char b;
B(int b):b(b){
}
void func(){
cout<<"B:"<<b;
}
};
//int A::b = 0;
int main(){
A a('a');
a.func();
B* b = reinterpret_cast<B*>(&a);
b->func();
}
我强制将A类的内存解释为B类,同样可以运行。
(4)const_cast
const_cast用于将一个变量的const限定消除。可能会引发异常。例如如果我将一个指向const定义的全局变量的指针变为了非const并赋值,那么由于全局const位于只读的段,会引发异常。
#include <iostream>
using namespace std;
const int num=10;//位于常量段
int main(){
const int* a = #
int *b = const_cast<int*>(a);
cout<<++*b<<endl;//会异常
cout<<num<<endl;
}