6.c++语言级别的类型转换
c++语言级别的类型转换
const_cast:去掉常量属性的一个类型转换
static_cast:提供比编译器认为安全的类型转换
reinterpret_cast:提供C风格的强制类型转换
dynamic_cast:主要在继承结构中,可以支持RTTI类型识别的上下类型转换
const_cast
int main() {
int a = 10;
const int* p = &a;
int *q = const_cast<int*>(p);
// char *q = const_cast<char*>(p); 报错
//double *q = const_cast<double*>(p); 报错
*q = 20;
cout<<a<<" "<<*q<<endl;
return 0;
}
/*
const_cast<type>(express)的type只接受express本身类型的指针后引用
*/
const_cast使用格式:const_cast(expression)
适用场景:用来移除非 const 对象的引用或指针的常量性(const),使用const_cast去除 const 对于引用和指针的限定,通常是为了函数能够接受参数或返回值。注意:目标类型只能是指针或引用,const_cast是对const的一种补充
//const_cast只能作用于指针或引用,去const化
int main()
{
//对于引用
int a = 100;
const int& ra = a; //此时ra的值不可以发生改变
const_cast<int&>(ra) = 300; //对ra进行去const化,ra的值就可以发生改变
cout << ra << " " << a << " ";
//对于指针
const int* p = &a;
*const_cast<int*>(p) = 100;
cout<<a;
}
终端输出: 300 300 100
那么如果对象是const类型的呢?
int main()
{
const int a=100;
const int&ra = a;
const_cast<int&>(ra) = 200;
cout << a << " " << ra << endl;
}
终端输出: 100 200 //这不同于非const对象,但是ra与a的值就不同了,这只改变了ra的值但没有改变a的值
那么再看一个
struct Node
{
int a;
};
int main()
{
const Node st = { 40 };
const Node& pd = st;
const_cast<Node&>(pd).a = 100;
cout << pd.a << " " << st.a;
}
终端输出: 100 100 //很奇怪,这怎么又相等了
结论:const_cast只有对非const变量使用const的指针或引用是安全的,若原生就是const的,再对const_cast后的指针或引用执行写操作是未定义的
static_cast
static_cast
语法格式:static_cast
适用场景:再一个方向上可以作隐式转换,再另一个方向上就可以作静态转换
int main()
{
//双隐
double d;int i;
//d = i;i = d; //两个方向都是被允许的,称为双隐式转换
d = static_cast<double>(i);
i = static_cast<double>(d);
d = static_cast<double>(10/3);
//单隐
void *P;int* p;
//p = q是可以的,q = p不可以,void*类型可以被任意指针类型赋值
q = static_cast<int *>(p);
//再比如malloc函数
q = static_cast<int*>(mallloc(sizeof(10)*10));
}
reinterper_cast
与C语言相同
dynamic_cast
主要用于继承结构,可以支持RTTI类型识别的上下转换
//学好c++还需知道的底层知识
#include <iostream>
using namespace std;
class Base
{
public:
virtual void func() = 0;
};
class Derive1 : public Base
{
public:
void func(){cout<<"Derive1::func()"<<endl;}
int d1;
};
class Derive2 : public Base
{
public:
void func(){cout<<"Derive2::func()"<<endl;}
//实现了新的API接口
void derive2func(){cout<<"derive2func()"<<endl;}
int d2;
};
void func(Base* b)
{
/*
* dynamic_cast会检查指针或引用是否会指向一个Derive2类型
* 通过p -> vfptr -> RTTI 来确定
* 如果确认指向的就是Derive类型没那么就返回一个指向Derive类型的指针
* 否则返回空指针nulllptr
* */
Derive2 *p = dynamic_cast<Derive2*>(b);
if(p == nullptr)
{
b->func();
}
else {
p->derive2func();
cout<<p->d2;
}
}
/*需求:
* 只要是Derive2就调用新的APIderive2func
* 其他的调用func()
*
* 这就要求可以识别传入引用的类型
* */
int main()
{
Derive1 d1;
Derive2 d2;
func(&d1);
func(&d2);
return 0;
}
static_cast是静态类型转换,但dynamic_cast 是动态类型转换可以识别RTTI类型