C++_强制类型转换

       

目录

1、C++新增转换符的原因

2、类型转换的概念

3、C++强制类型转换

3.1 static_cast

3.2 reinterpret_cast

3.3 const_cast 

3.4 dynamic_cast

结语 


前言:

        C++为了规范强制类型转换的可观性与安全性,引入了4种强制类型转换符,他们分别是:static_cast、reinterpret_cast、const_cast、dynamic_cast。

1、C++新增转换符的原因

        因为c语言的类型转换存在一些缺点,虽然c语言的转换风格简单易懂,但是有些场景下会导致数据精度的丢失不易被发现,即隐式类型转换的代码可读性不强, 而显示类型转换(强制转换)可以让多种类型之间相互转换,不够规范。

2、类型转换的概念

        由于C++兼容c语言,因此C++对类型转换的概念是沿用c语言的概念,只不过在其基础上做了优化,当两个对象之间发生了赋值或拷贝,而这两个对象的类型又不一样,就会发生类型转换,并且转换的类型是以被执行对象的类型为基准进行转换,比如赋值运算符的左右两侧类型不相同,或者函数的实参传给形参的类型不相同,又或者函数返回值与接收值类型不相同,这些场景下都会发生类型转换。

        c语言对类型转换有两种定义:

        1、隐式类型转换、即两个转换对象的类型不一样,让编译器完成他们之间转换,若他们之间不能转换则会报错。

        2、显示类型转换、又称强制类型转换,由程序员手动干预转换过程,通常在执行对象的前面加小括号,小括号里写转换之后的类型。

        类型转换测试代码如下:

#define _CRT_SECURE_NO_WARNINGS 1

#include<iostream>
using namespace std;

int main()
{
	int i = 12;

	// 隐式类型转换
	double d = i;
	printf("%d, %f\n", i, d);
	int* p = &i;

	// 显示的强制类型转换
	int address = (int)p;
	printf("%x, %d\n", p, address);

	return 0;
}

         运行结果:

        转换过程细节图:

 

3、C++强制类型转换

3.1 static_cast

         static_cast的效果类似上文提到的隐式类型转换,只不过他可以提高代码的可读性,让程序员一眼就可以看出转换之后的类型,具体示例如下:

#define _CRT_SECURE_NO_WARNINGS 1

#include<iostream>
using namespace std;

int main()
{
	double d = 3.141596;
	int a = static_cast<int>(d);//static_cast的用法,<>中表示转换后的类型
	cout << a << endl;
	return 0;
}

        运行结果:

        值得注意的是, static_cast不支持两种毫不相干的类型进行转换,比如int类型不能转换为string类型,如下图:

3.2 reinterpret_cast

         reinterpret_cast可以将位操作数上意义近似的两种不相关的类型进行转换,他带有“重新解释”的意思,比如将int类型转换为指针类型,示例代码如下:

#define _CRT_SECURE_NO_WARNINGS 1

#include<iostream>
using namespace std;

int main()
{
	int a = 12;

	int* p = reinterpret_cast<int*>(a);
	cout << p << endl;

	// 这里使用static_cast会报错
	//int *p = static_cast<int*>(a);
	return 0;
}

        运行结果:

        但是reinterpret_cast同样不能将int类型转换为string类型。

3.3 const_cast 

         const_cast可以让一个被const修饰的变量去掉其const的属性,即可以对该变量赋值。注意:const_cast的<>中只能是指针或引用,即const_cast转换后的类型只能是指针或引用。

        测试代码如下:

#define _CRT_SECURE_NO_WARNINGS 1

#include<iostream>
using namespace std;

int main()
{
	//若不加volatile,则修改的寄存器中的a,并不是内存中的a
	volatile const int a = 2;
	int* rp = const_cast<int*>(&a);//去掉了a的const,则可以通过指针修改他

	*rp = 3;
	cout << a << endl;
	cout << *rp << endl;
	
	return 0;
}

        运行结果:

         值得注意的是,const_cast的目的是为赋值一个可以更改const变量的指针或引用,并不是消除某个具有const属性的const,比如上述代码,可以通过rp更改a,但是a的本身还是不能够更改。

3.4 dynamic_cast

         dynamic_cast作用于继承场景下并且父类必须含虚函数(即满足多态类型),将一个指向父类对象的指针/引用转换为一个指向子类对象的指针/引用,又称为动态转换。

        多态的指针或引用转换分两种情况:

        1、向上强制转换,即子类指针/引用->父类指针/引用,这种情况下可以正常转换,因为可以看成是一种权限缩小的过程。

        2、向下强制转换,即父类指针/引用->子类指针/引用,这种情况下就必须要用dynamic_cast进行转换了。

        值得注意的是:并不是只要使用了dynamic_cast就能实现父类指针/引用->子类指针/引用,在某些场景是实现不了转换的,比如一个指向父类对象的指针,若将他转换成子类指针则会发生越界访问,具体示意图如下:

        以上情况dynamic_cast是不会发生转换的,他会返回0表示转换失败。


        只有当父类指针指向的空间是一块子类类型的空间,此时想把该父类型指针转换为子类型指针则可以成功,如下图所示:


        dynamic_cast测试代码如下: 

#define _CRT_SECURE_NO_WARNINGS 1

#include<iostream>
using namespace std;

class A
{
public:
	virtual void f() {}
};
class B : public A
{
public:
	int a;
};
void fun(A* pa)
{
	// dynamic_cast会先检查是否能转换成功,能成功则转换,不能则返回
	B* pb1 = static_cast<B*>(pa);//不安全的转换
	B* pb2 = dynamic_cast<B*>(pa);//安全的转换

	cout << "pb1:" << pb1 << endl;
	cout << "pb2:" << pb2 << endl;
}
int main()
{
	A a;
	B b;
	fun(&a);//a的类型是父类,无法转换
	fun(&b);//b的类型是子类,可以转换
	return 0;
}

        运行结果:

        从结果可以看到,dynamic_cast相比于直接转换其实是更加安全的,只有出现越界访问的风险,dynamic_cast就直接返回0,即nullptr。

结语 

        以上就是关于C++强制类型转换的讲解,上文介绍了四种强制类型转换符,他们的作用不仅仅是提高可读性,还有着安全检测的作用,因此使用这四种转换符可以提高代码的规范性。最后希望本文可以给你带来更多的收获,如果本文对你起到了帮助,希望可以动动小指头帮忙点赞👍+关注😎+收藏👌!如果有遗漏或者有误的地方欢迎大家在评论区补充,谢谢大家!!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

安权_code

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

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

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

打赏作者

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

抵扣说明:

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

余额充值