我的编程空间,编程开发者的网络收藏夹
学习永远不晚

C++实例讲解四种类型转换的使用

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

C++实例讲解四种类型转换的使用

C++类型转换

C语言风格的转换

C语言提供了自己的一套转换规则,有好处也有坏处。

C语言的风格:(type_name)expression;

C语言提供了隐式类型转换和显式类型转换。显式类型转换一般也叫做强转,隐式类型转换编译器完成,如果转换不了就报错。

而C语言类型转换的风格好处就是简单,缺陷比如转换的可视性差,显式类型转换的写法就只有一种,难以精准的跟踪错误。

?char ch=1.1,char ch=1在.cpp下都是合法的,这就是隐式类型转换,C语言下如果把一个结构体给int就会报错,因为编译器不知道怎么去转,C++下可以通过实现operator int()实现类型转换或者提供合适的构造函数完成隐式类型转换,下面以在.cpp中实现operator int()为例

下面这段代码由于隐式类型转换导致了死循环

C语言的类型转换其实已经足够完成需求了,但是可视性不太好,比如你不能在代码库中搜索它(就一对括号怎么去搜索),所以C++提供了一套类型转换,相当于语法糖了,此外还会进行一些编译性检查(比如dynamic_cast转换失败则返回空指针)。但其实作用都是一样的。

C++风格的类型转换

C++标准为了增加类型转换的可见性,提供了四种类型转化的方式。

static_cast

静态类型转换,进行相关类型的转换,但不能转换两个不相关的类型(即编译器看到这个转换是行不通的就会报错)。

static_cast < type-id > ( expression )

int main()
{
	double a = (int)5.5 + 5.3;//结果是10.3
	double b = static_cast <int>(5.5) + 5.3;
	cout << "a: " << a << endl;
	cout << "b: " << b << endl;
	return 0;
}

转换不相关的类型:

reinterpret_cast

很暴力的一个操作符,由英文直译过来就是重新解释的转型。白话就是将一段内存重新解释。

网上看到很多大佬的理解,这里借用或掺杂自己的思想:static_cast是做类型能做的转换,不行编译器就报错,告诉你这样是不合理的,reinterpret_cast则是就算不能转换编译器你也别报错,我心里有数。由于reinterpret_cast本质上是一个编译器指令,所以实际动作完全取决于编译器,失去了移植性。

暴力归暴力,但也是合理范围内的,比如你把一个结构体硬塞给int肯定是不行的,但是把结构体指针重新解释为int那是一点问题没有。

此外reinterpret_cast重新解释的办法是把那一块内存的比特位全部复制下来重新解释。

下面的例子把一个结构体指针解释为int再加上5.3。

struct Test
{
	int a;
};
int main()
{
	Test* t = new Test;
	double c = reinterpret_cast <int>(&t) + 5.3;
	cout << c << endl;
	return 0;
}

const_cast

删除变量的const属性,一般和指针或引用连用

int main()
{
	const int a = 1;//a是常变量,在栈上
	int* p = const_cast<int*>(&a);
	*p = 2;
	cout << a << endl;
	cout << *p << endl;
	return 0;
}

volatile const int a=1;//打印的a就会是2

volatile后编译器对访问该变量的代码不再优化。比如上面那句代码打印1就是因为编译器优化,读取的a是从寄存器中读取的,而不是内存。

多线程中也有很多关于 volatile的应用。

dynamic_cast

dynamic_cast,安全的向下转型。

多态的转换中向下转型(父类转为子类)用dynamic是安全的,但是父类必须有虚函数,否则编译报错,且只能用于指针或引用。

向上转型,子类给父类,发生切割,不需要转换。

向下转型,父类地址给子类指针,需要类型转换,由于是类型是子类指针,但是给的地址是父类的,如果用指针去访问子类独有的数据可能就会造成越界,然后程序就可能崩了,所以此时就需要dynamic_cast进行转换了,因为dynamic_cast会检查父类指针是否指向的是这个子类,如果是父类说明可能带来一些安全问题,会转换失败返回空指针,反之则实现转换。

理解向下转型不安全有个例子:男人是人,但人不一定是男人(男人派生自人,男人的指针=(男人类型的指针强转)人的地址,此时如果通过男人指针去调用男人自己独有的特性就是越界,因为实际上拿到的是人的地址,并没有存储男人的特性,也可以从空间大小上来解释,人是父类,空间更小,男人是子类,空间更大,给的是小空间,却有了访问大空间的能力,所以可能造成越界,所以是不安全的)

此外在一个父类有多个子类且需要类型转换时,dynamic_cast也能起到作用,举个例子

//父类是Entity,子类是Player和Enemy, e,player,enemy分别表示他们对应的实例化对象
Entity* p=&player;
Enemy* p1=(Enemy*)p;//向下转型需要强转,这样搞就出问题了,p明明指向的是一个player,现在类型为Enemy的指针居然指向了一个Player的对象,如果对其内存进行了操作,那后果是不可预料的。

父类指针一开始指向一个父类对象,再给到子类类型的指针,存在越界的风险,如果为了保证安全则需要检查。

父类的指针指向子类对象(向上转型),再给到子类指针,合理。

所以建议使用dynamic_cast,因为可以保证安全, 转换失败返回空指针(NULL)。

dynamic_cast的底层与RTTI有关,借助RTTI拿到类型信息,所以dynamic_cast更像一个函数,因为不是编译指令,所以会带来一些性能的损失。

RTTI 是“Runtime Type Information”的缩写,意思是运行时类型信息。RTTI存储了所有类型运行时的类型信息,增加了开销但是可以让我们做更多的操作。dynamic_cast的底层就是借助了RTTI+匹配,具体的不太了解。VS可以关闭RTTI,但是也就不能用dynamic_cast了

下面给一个代码例子

class Entity
{
public:
	virtual void Print() {};//dynamic_cast使用的前提必须是父类有虚函数
};
class Player:public Entity
{
};
class Enemy :public Entity
{
};
void Check(void* p)
{
	if (p)
	{
		cout << "转换成功" << endl;
	}
	else
	{
		cout << "转换失败" << endl;
	}
}
int main()
{
	Entity* e = new Entity();
	Entity* actuallyPlayer = new Player();//向上转型
	//安全的向下转型
	Player* player =(Player*)actuallyPlayer;//向下转型需要转换类型
	Player* player2 = dynamic_cast<Player*>(actuallyPlayer);
	Check(player2); cout << endl;
	//不安全的向下转型
	Player* player3 = (Player*)e;
	Player* player4 = dynamic_cast<Player*>(e);
	Check(player4); cout << endl;
	Entity* actuallyEnemy = new Enemy();
	Player* player5 = dynamic_cast<Player*>(actuallyEnemy);
	Check(player5); cout << endl;
	return 0;
}

dynamic也常常利用返回值是否是空指针来判断指针具体指向谁。

用dynamic_cast的地方其实也可以用static_cast,不过static_cast不会进行安全检查,如果你很清楚其指向,并且在安全的前提下,为了减少程序开销那可以考虑用static_cast

小结

  • static_cast用于相关类型的转换
  • reinterpret_cast用于重新解释内存(很暴力,用的时候心里要有数)
  • const_cast常用来取出const属性,常与指针连用来修改const变量的值
  • dynamic_cast,在多态里提供安全的向下转换(转换不安全就返回空指针,只要对返回的指针进行判断我们就能知道此次转换安不安全了)

到此这篇关于C++实例讲解四种类型转换的使用的文章就介绍到这了,更多相关C++类型转换内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

C++实例讲解四种类型转换的使用

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

C++的四种类型转换

这篇文章主要介绍了C++的四种类型转换,有详细的示例代码展示,对于学习C++的同学有一定的参考价值,感兴趣的同学可以参考本文
2023-05-14

详解C++中四种类型的转换

这篇文章主要是想和大家一起聊聊来C++中的四种类型转换 :const_cast、static_cast、reinterpret_cast和dynamic_cast,感兴趣的可以了解一下
2022-12-08

C++中的四种类型转换符是什么

本篇内容介绍了“C++中的四种类型转换符是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!一:背景在玩 C 的时候,经常会用 void*
2023-07-02

C++中的四种强制类型转换介绍

这篇文章主要讲解了“C++中的四种强制类型转换介绍”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“C++中的四种强制类型转换介绍”吧!在了解c++的强制类形转换的时候,先看看在c语言中是怎么进
2023-06-20

C++中四种类型转换的方法是什么

这篇文章主要介绍了C++中四种类型转换的方法是什么的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇C++中四种类型转换的方法是什么文章都会有所收获,下面我们一起来看看吧。一、隐式类型转换和显示类型转换当等号两边的
2023-07-05

C++11中explicit类型转换运算符的实例用法

这篇文章主要介绍“C++11中explicit类型转换运算符的实例用法”,在日常操作中,相信很多人在C++11中explicit类型转换运算符的实例用法问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”C++11
2023-06-19

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录