C++_类型转换

学习目标:

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

1.static_cast

2. reinterpret_cast

3.const_cast

4. dynamic_cast


学习过程

类型转换是我们日常学习和写代码总会遇见的事件,在学习C语言时,我们就经常会碰到隐式类型转换,对于一些系统接口函数,我们又需要显示类型转换。 对于这些类型转换,显示的还好些,隐式类型的转换就有些麻烦,因此C++提出了自己的类型转化风格,注意因为C++要兼容C语言,所以C++中还可以使用C语言的
转化风格。

1.static_cast

static_cast用于非多态类型的转换(静态转换),编译器隐式执行的任何类型转换都可用static_cast,但它不能用于两个不相关的类型进行转换。
所谓相关就是像double、int、long int 这些类型就是互相相关类型。
不相关就是像指针,int 等类型就是互相不相关类型。

使用static_cast的场景一般是在会发生隐式类型转换的时候。

int main()
{
	double a = 10.12;
	int i = static_cast<int> (a);
	std::cout << i << std::endl;
	return 0;
}

在这里插入图片描述

2. reinterpret_cast

reinterpret_cast操作符通常为操作数的位模式提供较低层次的重新解释,用于将一种类型转换为另一种不同的(不相关的)类型。

int main()
{
	int i = 10;
	int* pi = reinterpret_cast<int*> (10);
	std::cout << pi << std::endl;
	return 0;
}

在这里插入图片描述


3.const_cast

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

int main()
{
	const int i = 20;
	int* p = const_cast<int*> (&i);
	*p = 13; //*p修改数据, i的数据是否修改了呢? 
	std::cout << i << std::endl; 
	return 0;
}

在这里插入图片描述
这里我们看到打印出来的i的值并没有随着*p的赋值变为13,这是否说明我们的i的值并没有没修改呢?
实际上这是因为编译器的优化导致的,由于i为const属性,所以编译器在打印i时,直接将早已被保存在寄存器的i的初始值10进行打印了,并没有去访问内存。 (在之前我们学习多线程也遇到过这种情况,我们是使用volatile关键字来解决的)

int main()
{
	//const int i = 20;
	volatile const int i = 20;
	int* p = const_cast<int*> (&i);
	*p = 13;
	std::cout << i << std::endl;

	return 0;
}

在这里插入图片描述

4. dynamic_cast

dynamic_cast用于将一个父类对象的指针/引用转换为子类对象的指针或引用(动态转换)
向上转型:子类对象指针/引用->父类指针/引用(不需要转换,赋值兼容规则)
向下转型:父类对象指针/引用->子类指针/引用(用dynamic_cast转型是安全的)
注意:

  1. dynamic_cast只能用于父类含有虚函数的类
  2. dynamic_cast会先检查是否能转换成功,能成功则转换,不能则返回0

对于向上转型,我们不需要使用dynamic_cast进行转换,因为它们由于继承的切片机制,他们在赋值上是允许的。
这里主要讨论向下转型,为什么说用dynamic_cast转型是安全的? 因为如果是向下转型,从内存来看,如果父类对象指针/引用访问到子类对象自有的成员,必然会发生越界访问的问题。 所以如果使用dynamic_cast进行转换,识别到是向下转型,就会返回0,这就避免了越界访问的风险。

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

void fun(A* pa)
{
	// dynamic_cast会先检查是否能转换成功,能成功则转换,不能则返回0
	B* pb1 = static_cast<B*>(pa);
	B* pb2 = dynamic_cast<B*>(pa);
	std::cout << "pb1:" << pb1 << std::endl;
	std::cout << "pb2:" << pb2 << std::endl;
}
int main()
{
	A a;
	B b;
	fun(&a);
	std::cout << std::endl;
	fun(&b);
	return 0;
}

在这里插入图片描述


相关推荐

  1. C++的类型转换

    2024-04-21 06:36:05       45 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-04-21 06:36:05       98 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-04-21 06:36:05       106 阅读
  3. 在Django里面运行非项目文件

    2024-04-21 06:36:05       87 阅读
  4. Python语言-面向对象

    2024-04-21 06:36:05       96 阅读

热门阅读

  1. 数据挖掘与数据分析

    2024-04-21 06:36:05       55 阅读
  2. C# 反射基础

    2024-04-21 06:36:05       40 阅读
  3. 浏览器原理之浏览器机制

    2024-04-21 06:36:05       41 阅读
  4. html5与css3前端学习笔记

    2024-04-21 06:36:05       32 阅读
  5. 分类与预测算法评价的介绍

    2024-04-21 06:36:05       36 阅读
  6. MySQL数据加密,模糊查询

    2024-04-21 06:36:05       33 阅读