c++中的四种cast转换

本文深入探讨C++中的类型转换,包括隐式和显式转换,重点解析static_cast、dynamic_cast、reinterpret_cast与const_cast的区别及应用。通过实例说明不同转换方式的特点与安全性,为读者提供全面的类型转换知识。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本章主要复习的是 类型之间的互相转换,类型好端端的为什么就要转换呢?因为像 C++ 语言是强类型的语言,所以在赋值或者运算的时候类型需要转换一致

那么在C语言中存在着隐式转换和显示转换着两种

// 隐式类型转换
int i = 1;
double d = i;
// 显示的强制类型转换
int* p = &i;
int address = (int)p;
printf("%x, %d\n", p, address);

缺陷: 转换的可视性比较差,你容易忽视它的转换,所有的转换形式都是以一种相同的形式书写,难以跟踪错误

所以引出了 C++强制类型转换

标准C++为了 加强类型转换的可视性 让你明确的知道,原来这个变量,这个类型已经转换为另一种类型了,就引入了四种命名的强制类型转换操作符:static_cast、reinterpret_cast、const_cast、dynamic_cast

当然这篇重要掌握的就是他们之间的区别?

static_cast 可以实现 C++内置基本类型的转换;

double d = 12.34;
int a = static_cast<int>(d); // a = 12

它也可以实现具有继承关系类型之间的转换

class Base{};
class Derived :public Base{};

Derived d;
Base e = staic_cast<Base>(d);

我们可以看出它是从派生类对象转换为基类对象,那么反过来可以吗?可以把基类对象转换为派生类对象吗?

不可以,编译器不允许我们这样做,因为会不安全!

试想如果把基类转换为派生类型的话,因为派生类可能会派生出基类没有的东西,所以如果让转换的那个对象去访问派生类成员,这个成员在基类可能不存在,这样就会引发错误!

dynamic_cast 和 static_cast 是相对的,static_cast 是在编译的时候进行转换的。它是动态的在运行时候转换的,而且 只能在继承类对象的指针或引用之间进行转换,在进行转换的时候,会根据当前RTTI (运行时类型识别)判断类型对象之间的转换是否合法,如果合法就转换成功了,返回了指向类的引用或指责,但是如果转换是非法的,则返回NULL或者0

使用 dynamic_cast 进行转换的时候,基类一定要有虚函数,另外它向上转换的时候是兼容的,向下转换的时候有类型安全检查,比static_cast 要安全

class A {
public:
	virtual void f() {}
};
class B : public A
{};

void fun(A* pa) {
	// dynamic_cast会先检查是否能转换成功,
	// 能成功则转换,不能则返回0
	cout << "pa" <<' '<< typeid(pa).name()<<pa << endl;

	B* pb1 = static_cast<B*>(pa);
	B* pb2 = dynamic_cast<B*>(pa);
	//pa   class A*  00AFFE00
	//pb1  class B*  00AFFE00
	//pb2  class B*  00000000 

	//pa   class A*  00AFFDF4
	//pb1  class B*  00AFFDF4
	//pb2  class B*  00AFFDF4
	cout << "pb1" <<' '<<typeid(pb1).name()<<' '<< pb1 << endl;
	cout << "pb2" <<' '<<typeid(pb2).name()<<' '<< pb2 << endl;
}
int main() {
	A a;
	B b;
	fun(&a);
	fun(&b);
	system("pause");
	return 0;
}

reinterpret_cast 类型转换函数 将一个类型的指针转换为另一个类型的指针。reinterpret 单词的汉语意思是重新解释,所以这种转换不需要修改指针变量值数据存放格式,只需在编译时重新编译解释指针的类型即可

就像这样

double d = 9.3;
double *pd = &d;
int *pi = reinterpret_cast<int*>(pd);

上面是将 double * 转换为 int * ,但是不可以用于非指针类型的转换,reinterpret_cast 同时也不能将一个const指针转换为void*指针

reinterpret_cast 这里是将一个整形函数转换为函数指针的类型去调用,但是存在着缺陷(了解)

typedef void(*FUNC)();
int DoSomething(int i){
	cout << "DoSomething" << endl;
	return 0;
}

void Test(){
	// reinterpret_cast可以编译 
	// 以FUNC的定义方式去看待DoSomething函数
	// 所以非常的BUG,下面转换函数指针的代码是不可移植的,
	// 所以不建议这样用
	
	// C++不保证所有的函数指针都被一样的使用,
	// 所以这样用有时会产生不确定的结果
	FUNC f = reinterpret_cast<FUNC>(DoSomething);
	f();
}

const_cast 最常用的用途就是删除变量的const属性,方便赋值

const int* pci = 0;
int* pj = const_cast<int*>(pci);

经过转换后的 pci 赋值给pj ,不在具备常量的属性,可以被修改

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序猿的温柔香

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值