cpp基础学习笔记03:类型转换

static_cast 静态转换

  • 用于类层次结构中基类和派生类之间指针或者引用的转换。up-casting (把派生类的指针或引用转换成基类的指针或者引用表示)是安全的;down-casting(把基类指针或引用转换成子类的指针或者引用)是不安全的。
  • 用于基本数据类型之间的转换,如把int转换成char,这种转换的安全性也要由开发人员来保证。
  • 可以把空指针转换成目标类型的空指针(null pointer)。
  • 把任何类型的表达式转换成void类型。
  • 注意: static_cast不能转换掉expression的const、volitale或者__unaligned属性。

基本类型转换:

#include <iostream>int main()
{int b = 20;float ft = 30.25f;b = static_cast<float>(ft);std::cout << "After static_cast b: " << b << std::endl;std::cout << "Finished! \n";return 0;
}

类的基本转换:

#include <iostream>class Base
{
public:Base(int data):_data(data){}void printData(){std::cout << "Base data: " << _data << std::endl;}private:int _data;
};class TestA : public Base
{
public:TestA(int num, int data): _num(num), Base(data){}void printData(){std::cout << "TestA Num: " << _num << std::endl;}private:int _num;
};int main()
{Base base{ 10 };TestA testA{ 10,20 };// 向上转换Base* base_ptr = static_cast<Base*>(&testA);base_ptr->printData();// 向下转换:危险行为TestA* test_ptr = static_cast<TestA*>(&base);test_ptr->printData();std::cout << "Finished! \n";return 0;
}

观察,向上转换正常,向下转换数据未定义。

dynamic_cast

typeid必须是类的指针、类的引用或者void*。如果typeid是类的指针类型,那么expression也必须是指针,如果typeid是一个引用,那么expression也必须是一个引用。一般情况下,dynamic_cast用于具有多态性的类(即有虚函数的类)的类型转换。

dynamic_cast依赖于RTTI信息,其次,在转换时,dynamic_cast会检查转换的source对象是否真的可以转换成target类型,这种检查不是语法上的,而是真实情况的检查。先看RTTI相关部分,通常,许多编译器都是通过vtable找到对象的RTTI信息的,这也就意味着,如果基类没有虚方法,也就无法判断一个基类指针变量所指对象的真实类型,这时候,dynamic_cast只能用来做安全的转换,例如从派生类指针转换成基类指针。而这种转换其实并不需要dynamic_cast参与。也就是说,dynamic_cast是根据RTTI记载的信息来判断类型转换是否合法的。

  • 主要用于类层次之间的up-casting和down-casting,还可以用于类之间的交叉转换。在进行down-casting时,dynamic_cast具有类型检查的功能,比static_cast更安全。检测在运行时进行。如果被转换的指针不是一个被请求的有效完整的对象指针,返回值为NULL。当用于多态类型时,它允许任意的隐式类型转换以及相反过程。不过,与static_cast不同,在后一种情况里(注:即隐式转 换的相反过程),dynamic_cast会检查操作是否有效。也就是说,它会检查转换是否会返回一个被请求的有效的完整对象。

  • 注意:dynamic_cast不能转换掉expression的const、volitale或者__unaligned属性。

测试,加入现在的基类没有定义虚函数:

class Base
{
public:Base(int data):_data(data){}void printData(){std::cout << "Base data: " << _data << std::endl;}private:int _data;
};class TestA : public Base
{
public:TestA(int num, int data): _num(num), Base(data){}void printData(){std::cout << "TestA Num: " << _num << std::endl;}private:int _num;
};int main()
{Base* base_ptr = new Base(10);TestA* test_ptr = new TestA(10,20);Base* ptr_01 = dynamic_cast<Base*>(test_ptr);ptr_01->printData();    // ok#if 0TestA* ptr_02 = dynamic_cast<TestA*>(base_ptr); // errorptr_02->printData();
#endifstd::cout << "Finished! \n";return 0;
}

重新定义并测试:

class VirtualBase
{
private:int _data;public:VirtualBase(int data): _data(data){}virtual ~VirtualBase(){}virtual void printData(){std::cout << "Virtual Base. Data: " << _data << std::endl;}
};class TestB : public VirtualBase
{
private:int _num;public:TestB(int num, int data): _num(num), VirtualBase(data){}~TestB(){}void printData() override{std::cout << "TestB. Data: " << _num << std::endl;}
};int main()
{// 定义VirtualBase* virual_base_ptr = new VirtualBase(30);TestB* test_b_ptr = new TestB(40, 50);// 派生类指向父类,okVirtualBase* ptr_03 = dynamic_cast<VirtualBase*>(test_b_ptr);ptr_03->printData();        // ok// 父类指向指向派生类,errorTestB* ptr_04 = dynamic_cast<TestB*>(virual_base_ptr);// ptr_04->printData();    // error// 转换失败返回了nullptr,所以一般需要额外判断if (ptr_04 != nullptr)ptr_04->printData();std::cout << "Finished! \n";return 0;
}

reinterpret_cast

转换一个指针为其他类型的指针,也允许将一个指针转换为整数类型,反之亦然。这个操作符能够在非相关的类型之间进行转换。操作结果只是简单的从一个指针到别的指针的值的二进制拷贝,在类型之间指向的内容不做任何类型的检查和转换。这是一个强制转换。使用时有很大的风险,慎用之。(反正少用就完事儿了)

const_cast

这个类型操纵传递对象的const属性,或者是设置或者是移除(也不常用)

参考资料

C++ | 四种类型转换_c++四种类型转换-CSDN博客

https://www.cnblogs.com/daihanlong/p/5550530.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/501578.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

XUbuntu22.04之如何找到.so库所在的软件包?(二百一十六)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a;多媒…

JVM内存模型深度剖析和优化

JVM内存模型深度剖析和优化 Java语言的跨平台性 问题: Java语言的跨平台性是如何做到的 通过不同操作系统平台的JVM版本&#xff0c;Linux和Windows的JVM版本各不相同Java是跨平台解释性语言&#xff0c;可以在不同的操作系统运行&#xff0c;JVM从软件层面屏蔽不同操作系统在…

JOSEF约瑟 JZS-7G-42 AC220V静态可调延时中间继电器 端子式导轨安装15ms-10s

系列型号&#xff1a;JZS-7G-57端子排延时中间继电器&#xff1b;JZS-7G-42X端子排延时中间继电器&#xff1b;JZS-7G-22X端子排延时中间继电器&#xff1b;JZS-7G-21端子排延时中间继电器&#xff1b;JZS-7G-41端子排延时中间继电器&#xff1b;JZS-7G-51端子排延时中间继电器…

大数据可视化python01

import pandas as pd import matplotlib.pyplot as plt# 设置中文改写字体 plt.rcParams[font.sans-serif] [SimHei]# 读取数据 data pd.read_csv(C:/Users/wzf/Desktop/读取数据进行数据可视化练习/实训作业练习/瓜果类单位面积产量.csv ,encoding utf-8)#输出 print(data)…

Docker Swarm全解析:实现微服务高可用与故障转移的秘密武器

&#x1f407;明明跟你说过&#xff1a;个人主页 &#x1f3c5;个人专栏&#xff1a;《Docker入门到精通》 《k8s入门到实战》&#x1f3c5; &#x1f516;行路有良友&#xff0c;便是天堂&#x1f516; 目录 一、基本概念和介绍 1、Docker Swarm 是什么&#xff0c;它与 …

#stm学习总结 (二十八)硬件随机数实验

28.1 随机数发生器简介 STM32F407 自带了硬件随机数发生器&#xff08;RNG&#xff09;&#xff0c;RNG 处理器是一个以连续模拟噪声为基础的随机数发生器&#xff0c;在主机读数时提供一个 32 位的随机数。 28.1.1 RNG 框图 STM32F407 的随机数发生器&#xff08;RNG&#x…

3dmax corona渲染器和vray渲染器哪个好?

Corona和Vray这两个渲染器都很不错&#xff0c;每个都有自己的优点和适用的情况&#xff0c;所以很难说哪个更好。 下面我简单给你对比一下&#xff1a; 1、操作界面&#xff1a;Vray的界面比较多&#xff0c;参数设置也复杂一点&#xff0c;初学者可能会觉得有点难上手。但C…

【cmu15445c++入门】(13)C++的std::promise

一、说明 std::promise 是C11并发编程中常用的一个类&#xff0c;常配合std::future使用。其作用是在一个线程t1中保存一个类型typename T的值&#xff0c;可供相绑定的std::future对象在另一线程t2中获取 二、代码 #include <chrono> #include <future> #includ…

零基础自学C语言|数据在内存中的存储

✈整数在内存中的存储 在讲解操作符的时候&#xff0c;我们就讲过了下面的内容&#xff1a; 整数的2进制表示方法有三种&#xff0c;即原码、反码和补码 三种表示方法均有符号位和数值位两部分&#xff0c;符号位都是用0表示"正"&#xff0c;用1表示"负"&…

【前端素材】推荐优质后台管理系统 Adminity平台模板(附源码)

一、需求分析 1、系统定义 后台管理系统是一种用于管理网站、应用程序或系统的管理界面&#xff0c;通常由管理员和工作人员使用。它提供了访问和控制网站或应用程序后台功能的工具和界面&#xff0c;使其能够管理用户、内容、数据和其他各种功能。 2、功能需求 后台管理系…

你用多久拿下了PMP(项目管理专业人士资格认证)?

大概1个月左右&#xff0c;一般的2个月左右也差不多了。 PMP考试现在是第七版的教材&#xff0c;跟考纲了&#xff0c;相对第六版的来说增加了很多敏捷题型&#xff0c;相对要灵活很多&#xff0c;难度也有所提升&#xff0c;我的备考经历给大家参考下&#xff0c;希望对你有帮…

移动互联网时代的APP上架流程和要点

摘要 本文将介绍移动应用程序上架的基本流程和要点&#xff0c;包括应用商店注册、APP材料准备、打包上传App、APP审核以及发布APP的详细步骤。此外&#xff0c;还会提到利用appuploder工具简化iOS应用上架步骤的方法&#xff0c; 引言 在移动互联网时代&#xff0c;开发一…