【C++】C++中的类型转换

在这里插入图片描述

🚀write in front🚀
📜所属专栏: C++学习
🛰️博客主页:睿睿的博客主页
🛰️代码仓库:🎉VS2022_C语言仓库
🎡您的点赞、关注、收藏、评论,是对我最大的激励和支持!!!
关注我,关注我,关注我你们将会看到更多的优质内容!!

在这里插入图片描述

前言

  在平常的学习中,类型的转换其实是不断在出现的,那么C++11相比于C语言的类型转换又有了哪些不同呢?这篇文章就来教会你C++里面的类型转换

一.回忆C语言的类型转换:

  在C语言中,如果赋值运算符左右两侧类型不同,或者形参与实参类型不匹配,或者返回值类型与接收返回值类型不一致时,就需要发生类型转化,C语言中总共有两种形式的类型转换:隐式类型转换和显式类型转换。

  1. 隐式类型转化:编译器在编译阶段自动进行,能转就转,不能转就编译失败
  2. 显式类型转化:需要用户自己处理
void Test ()
{
int i = 1;
// 隐式类型转换
double d = i;
printf("%d, %.2f\n" , i, d);
int* p = &i;
// 显示的强制类型转换
int address = (int) p;
printf("%x, %d\n" , p, address);
}

  不知道大家是否还记得C语言里面的一个大坑:

void insert(size_t n, char ch)
{
    int end = 10;
    while (end >= n)
    {
        cout << end << endl;
        end--;
    }
}

int main()
{
	insert(0,'ch');
}

  这段代码看上去感觉没有什么问题,但是当传的pos为0的时候,就会死循环,这就是隐式类型转化所导致的(int要转化为size_t,此时如果int为负数也会被转化为正数).
在这里插入图片描述

缺陷:

转换的可视性比较差,所有的转换形式都是以一种相同形式书写,难以跟踪错误的转换

二.C++强制类型转换:

标准C++为了加强类型转换的可视性,引入了四种命名的强制类型转换操作符

static_castreinterpret_castconst_castdynamic_cast
  这里的操作符的调用有点像函数对象调用函数 (哈哈哈)

1.static_cast:

  static_cast用于非多态类型的转换(静态转换),只适用于相关类型/相近类型的转换,比如将int存到double里面

	int a = 0;
	//C语言:
	//double d = a;
	//double d=(double)a;

	//C++:
	double d = static_cast<int>(a);

2.reinterpret_cast

  reinterpret_cast主要用于不相关类型之间的转换,比如将地址保存到整形

int* p1 = &a;
	//C语言:
	// int address = (int)p1;
	
	//C++
	int address = reinterpret_cast<int>(p1);

3.const_cast:

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

	//这里的n没有去内存取,可能是宏替换或者寄存器里取出来面
	//	const int n = 10;
	
	// volatile 修饰的变量,每次都要去内存取
	volatile const int n = 10;
	//C语言:(C语言指针类型都能强转)
	//转换有安全隐患
	//int *p2=(int*)&n;

	//C++:
	int* p2 = const_cast<int*>(&n);
	(*p2)=100;
	cout << "n:" << &n << " : " << n << endl;
	cout <<"p2:"<<p2<< " : " << *p2 << endl;

  这里注意的是,一定要加一个volatile关键字,让每次都去内存里面取,不然会出问题(相同地址但是值不同)。

4.dynamic_cast:

  dynamic_cast用于将一个父类对象的指针/引用转换为子类对象的指针或引用(动态转换)
  在之前继承的学习里面,我们学习了向上转换,是天然支持的,因为他的赋值兼容规则,只需对子类进行切片就可得到父类
  但是对于向下转换,由于指针是可以强行转化的,所以如果子类指针指向父类是没有错的,但是下面如果有调用成员,就会出问题(父类怎么调子类的成员,他根本没有)。所以为了使转化安全,就使用了dynamic_cast

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

	int _x = 0;
};

class B : public A
{
public:
	//int _y = 0;
};


void fun(A* pa)
{
	// pa是指向子类对象B的,转换可以成功,正常返回地址
	// pa是指向父类对象A的,转换失败,返回空指针
	B* pb = dynamic_cast<B*>(pa);
	if (pb)
	{
		cout << "转换成功" << endl;
		pb->_x++;
		//pb->_y++;
	}
	else
	{
		cout << "转换失败" << endl;
	}
}

int main()
{
	A aa;
	fun(&aa);

	B bb;
	fun(&bb);
}

  其实简单的说,dynamic_cast就是杜绝了向下转换的发生。如果转换失败,就置为空。

三.RTTI(了解)

RTTI:Run-time Type identification的简称,即:运行时类型识别。
C++通过以下方式来支持RTTI:

  1. typeid运算符
  2. dynamic_cast运算符
  3. decltype

总结

  更新不易,辛苦各位小伙伴们动动小手,👍三连走一走💕💕 ~ ~ ~ 你们真的对我很重要!最后,本文仍有许多不足之处,欢迎各位认真读完文章的小伙伴们随时私信交流、批评指正!

专栏订阅:
每日一题
C语言学习
算法
智力题
初阶数据结构
Linux学习
C++学习
更新不易,辛苦各位小伙伴们动动小手,👍三连走一走💕💕 ~ ~ ~ 你们真的对我很重要!最后,本文仍有许多不足之处,欢迎各位认真读完文章的小伙伴们随时私信交流、批评指正!

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

坤小满

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

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

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

打赏作者

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

抵扣说明:

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

余额充值