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(expresion)

适用场景:再一个方向上可以作隐式转换,再另一个方向上就可以作静态转换

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类型

posted @ 2022-10-21 17:21  satellite2002  阅读(31)  评论(0编辑  收藏  举报