C++四种类型转换总结

2021/7/1 12:21:36

本文主要是介绍C++四种类型转换总结,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

 

文章目录

    • 类型转换
      • C语言类型转换
      • C++类型转换
        • const_cast 去常属性
        • 寄存器骚操作
        • 关键字volatile
        • reinterpret_cast重解释
        • static_cast 静态类型转换
        • dynamic_cast 动态类型转换

 

类型转换

C语言类型转换

在C语言里面类型转换比较简单,直接 (转换类型) 类型 强转就可以转换

	int a = 10;
	//将int类型变量a强转成double类型变量
	double b = (double)a;//在这里并没有改变 a 的类型,只是编译器重新解释 a 的类型

C++类型转换

C++类型转换要求更为严格,总共分为四种类型转换运算符

关键字 功能
const_cast 去常属性
reinterpret_cast 重解释类型转换
static_cast 静态类型转换
dynamic_cast 动态类型转换

统一使用规范:关键字 (expression)

const_cast 去常属性

const_cast<转换类型>(变量);

#include<iostream>
using namespace std;
int main()
{
	int temp = 49;
	const int * p1 = &temp;	//不能通过指针修改指针指向的值 
	int* p2, *p3;
	/***C类型转换***/
	p2 = (int*)p1;	
	*p2 = 10;
	cout << *p2 << endl;
	/***C++类型转换***/
	p3 = const_cast<int*>(p1);	//去常属性
	*p3 = 20;
	cout << *p3 << endl;
	return 0;
}
打印结果
10
20

寄存器骚操作

在去常属性里面还有个有趣的现象

#include<iostream>
using namespace std;
int main()
{
	int const tmp = 100;	//定义常量tmp tmp不能修改
	int const* p = &tmp;	//不能通过指针修改指向的值 
	int* const q = const_cast<int*>(p); //去常属性 可以通过指针修改指向的内容
	*q = 200;
	cout << tmp << " " << *p << " " << *q << endl;	//打印变量的值
	cout << &tmp << endl << p << endl << q << endl;	//打印变量地址
	return 0;
}
打印结果
100 200 200
0086F9D0
0086F9D0
0086F9D0

what?什么,地址一样,打印结果不一样,不是应该一样的吗!!!

既然标题是寄存器骚操作,那原因肯定和寄存器有关

这个其实是编译器的一个优化,当定义常量时

int const tmp = 100;	//定义常量tmp tmp不能修改

我们就相当于和编译器约定好了,我们不会去修改tmp的值,这个时候编译器就会做一个优化,将tmp的值,放到寄存器里面,然后读取tmp时直接在寄存器里面读取,加快读取速度。

这个时候我们有去常属性const_cast,动过变量q修改tmp在内存中的值

*q = 200;

在打印结果时,tmp读取的是寄存器的值,p ,q读取的是内存的值

cout << tmp << " " << *p << " " << *q << endl;	//打印变量的值

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5BvhScSY-1624967855258)(D:\微信公众号\Typora\C++\类型转换\寄存器.png)]

关键字volatile

上面这种优化肯定要不得,所以有一个关键字来解决这种不好的优化问题,那就是volatile,英文翻译:易变的; 无定性的;其实就是告诉编译器这个关键字修饰的变量不安全,你要到内存里面去操作,不要优化

volatile int const tmp2 = 100;
volatile int const* pm = &tmp2;   //不能通过指针修改指向的值 
int* const qm = const_cast<int*>(pm); //q本身只读  指向读写 
*qm = 200;
cout << tmp2 << " " << *pm << " " << *qm << endl;
cout << (void*)&tmp2 << endl << (void*)pm << endl << qm << endl;
打印结果:
200 200 200
007CFDDC
007CFDDC
007CFDDC

这样就不会出现地址一样,数值不一样的情况了

reinterpret_cast重解释

reinterpret_cast运算符用于天生危险的类型转换,它不允许删除const,用法和const_cast一样:<reinterpret_cast>(转换类型)

其实和强转并没有什么太大的区别,用个例子来简单说明下

#include<iostream>
using namespace std;
int main()
{	
    int* pi = new int(10);
	//double* pd = pi; int* 不能直接转换成 double* 
    /***C++类型转换***/
	double* pd = reinterpret_cast<double*>(pi);
    /***C类型转换***/
	//double* pd = (double*)pi;
	cout << *pi << " " << *pd << endl;
    //将整型重新解释为指针
	int addr = 0x12345678;   // 78 56 34 12
	char* pc = reinterpret_cast<char*>(&addr);

	for (int i = 0; i<4; ++i) {
		cout << showbase << hex << (int)*(pc + i) << " ";
	}
 	return 0;
}
打印结果:
10 -7.84591e+298
0x78 0x56 0x34 0x12

static_cast 静态类型转换

  • 非const转const、void*转指针
	//将基本类型转化成void类型指针 
	double num = 12.12;
	void* vp = static_cast<void*>(&num);
	const double* cnum = static_cast<const double*>(vp);
	cout << typeid(*cnum).name() << endl;
  • 多态向上转化,多态向下转化(不安全)

有四个类Base,Parent,Chile,Other,继承关系如下

class Base
{
public:
	virtual void foo(){
		cout << "Base::foo" << endl;
	}
	int m_a{ 5 };
};

class Parent :public Base
{
public:
	void foo(){
		cout << "Parent::foo" << endl;
	}
	int m_b{ 10 };
};

class Child :public Parent
{
public:
	void foo(){
		cout << "Chile::foo" << endl;
	}
};
class Other
{
public:
	void foo(){
		cout << "Other::foo" << endl;
	}
};

向上造型 上行转换 安全

	Parent b;
	Base* pa = static_cast<Base*>(&b); //基类指针指向子类对象  向上造型 上行转换 安全 
	pa->foo();	//由多肽性质可知调用的是Parent::foo

向下造型 下行转换 不安全 不允许出现下面情况

	Base a;
	Parent* pb = static_cast<Parent*>(&a);//向下造型 下行转换  不安全 

dynamic_cast 动态类型转换

  • 用于动态类型转换。只能用于含有虚函数的类,用于类层次间的向上(向上造型不检查)和向下(向下造型借助RTTI检查)转化。

  • 只能转指针或引用

  • 向下转化时,如果是非法的对于指针返回NULL,对于引用抛bad_cast异常

RTTI 运行时类型识别

RTTI只能用于包含虚函数的类

	Parent p;
	Child* pc = static_cast<Child*>(&p);
	cout << "chile:" << pc << endl;
	Child *pcc = dynamic_cast<Child*>(&p);
	cout << "chile:" << pcc << endl;
	//Child &pccc = dynamic_cast<Child&>(&p); 抛出异常

 



这篇关于C++四种类型转换总结的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程