【C++】-c++的类型转换


作者:小树苗渴望变成参天大树
作者宣言:认真写好每一篇博客
作者gitee:gitee✨
作者专栏:C语言,数据结构初阶,Linux,C++ 动态规划算法
如 果 你 喜 欢 作 者 的 文 章 ,就 给 作 者 点 点 关 注 吧!

文章目录

  • 前言
  • 一、C语言的类型转换
  • 二、为什么C++需要四种类型转换
  • 三、 C++强制类型转换
    • 四、总结


前言

今天将一个知识量不是很大,而且建议使用的东西,相信大家看到类型转换的时候就觉得这不是C语言的时候就学了吗??为什么现在拿出来提,但又看到C++的类型转换,说明这是C++新出来的,大家都是知道C++是兼容c语言的,所以再C里面的类型转换再C++里面也适用,而今天将的是C++里面的类型转换,是为了规范C语言里面类型转换出现的不安全问题,所以,接下来我们就来进入正文进行讲解。


一、C语言的类型转换

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

显示类型转换:
我们来看案例:

int main()
{
	//显示的类型转换

	//相关类型的显示类型转换
	int i = 0;
	int* p = &i;  
	int address = (int)p;

	double b = 1.1;//可能会造成精度丢失
	i = (int)b;

	//不相关类型的显示类型转换
	vector<int> v;
    string s;
    v = (vector<int>)s;
	return 0;
}

隐式类型转换:

void insert(size_t pos, char ch)
{
	int end = 10;
	while (end >= pos)//会进行隐式类型转换,将end类型转换成int,会死循环
	{
		cout << end << endl;
		//...
		--end;
	}
}

double b = 1.1;
i = b;

const变量也可以修改

	const int n = 10;
	//转换有安全隐患的
	int* p = (int*)&n;
	(*p)++;
	
	cout << n << endl;
	cout << *p << endl;

【C++】-c++的类型转换_第1张图片

大家看到从监视窗口看到的值和打印的值不一样,原因就是监视窗口里面的值是内存里面里面的值,而打印的时候没有直接去内存里面去拿值,而是再寄存器的时候直接进行的替换,我们可以使用一个关键字让他到内存里面取volatile
【C++】-c++的类型转换_第2张图片
上面的办法就是让const去掉常性。

上面的几种场景我们发现都可能会出现问题,而且每种转换可视性较差,所以的转换都是相同的方式,再前面加类型就可以,看需要人自己来判断。

二、为什么C++需要四种类型转换

C风格的转换格式很简单,但是有不少缺点的:

  1. 隐式类型转化有些情况下可能会出问题:比如数据精度丢失
  2. 显式类型转换将所有情况混合在一起,代码不够清晰
    因此C++提出了自己的类型转化风格,注意因为C++要兼容C语言,所以C++中还可以使用C语言的转化风,但是建议使用c++11出来的风格。

三、 C++强制类型转换

标准C++为了加强类型转换的可视性,引入了四种命名的强制类型转换操作符:
static_cast、reinterpret_cast、const_cast、dynamic_cast
(1)static_cast用于非多态类型的转换(静态转换),编译器隐式执行的任何类型转换都可用
static_cast,但它不能用于两个不相关的类型进行转换


double b = 1.1;
i = static_cast<int>(b);

这样就可以很好的知道这是隐式类型转换。

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

double d = 12.34;
 int a = static_cast<int>(d);
 cout << a << endl;
 // 这里使用static_cast会报错,应该使用reinterpret_cast
 //int *p = static_cast(a);
 int *p = reinterpret_cast<int*>(a);

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

  int* p = const_cast< int*>(&a );
  *p = 3;
  cout<<a <<endl;

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

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

这是指针c++特有的,c语言没有继承
我们来看一个例子:

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

	int _x = 0;
};

class b : public a
{
public:
	int _y = 0;
};
void fun(A* pa)
{
	B* pb = (B*)pa;
	pb->_x++;
	pb->_y++;
}

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

	B bb;
	fun(&bb);

	return 0;
}

我们再传参的时候,形参接收实参的过程是向上转型没有问题,但是函数体里面有一个将父类指针强转给子类指针,第一中会报错,原因是,我们B*让pa的访问范围变大了,本来就智能访问_x,现在可以访问_y,而A类里面没有_y就会报错,这种错误我们是很难知道的,所以需要使用 dynamic_cast

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;
	}
}

【C++】-c++的类型转换_第3张图片
这样就很好的避免我们上面会出现到的问题了
注意

强制类型转换关闭或挂起了正常的类型检查,每次使用强制类型转换前,程序员应该仔细考虑是
否还有其他不同的方法达到同一目的,如果非强制类型转换不可,则应限制强制转换值的作用
域,以减少发生错误的机会。强烈建议:避免使用强制类型转换

四、总结

到这里面我们的类型转换就讲解完毕了,大家再平时中试着慢慢使用这些,对以后再开发中又帮助,可以帮助我们减少很多不必要的麻烦,这节的内容不难,大家下来好好的去理解一下,我么拿下篇介绍特殊类的设计。

你可能感兴趣的:(C++进阶,c++,java,开发语言)