c++ dynamic_cast,static_cast,const_cast,reinterpret_cast四种cast用法整理

news2024/10/7 10:18:40

在C++中主要分为四种cast,分别是:static_cast、dynamic_cast、const_cast和reinterpret_cast

dynamic_cast动态类型转换

首先,我们明确基类和派生类之间的两个转换术语
向上转换(upcast):派生类向基类转换
向下站还(downcast):基类向派生类转换
下面就上面两种类型转换,说明一下dynamic_cast在其中的情况
dynamic_cast转换的base类至少带有一个虚函数
对于向上类型转换的时候,总是成功并且安全的
对于向下类型转换不都是成功的对于指针,如果转换不成功,返回空指针。对于引用,如果转换不成功,则会跑出异常(std::bad_cast)

1.向上转换是正确的

class Base
{
public:
    Base(){};
    virtual void Show(){cout<<"This is Base calss";}
};
class Derived:public Base
{
public:
    Derived(){};
    void Show(){cout<<"This is Derived class";}
};
int main()
{
    Base *base ;
    Derived *der = new Derived;
    //base = dynamic_cast<Base*>(der); //正确,但不必要。
    base = der; //先上转换总是安全的
    base->Show();
    system("pause");
}

2.dynamic_cast与继承层次的指针
有两种情况:
第一种基类指针所指的对象是派生类类型,第二种是基类指针所指对象是基类类型,dynamic_cast在运行是检查转换失败返回0

#include "stdafx.h"
#include<iostream>
using namespace std;

class Base
{
public:
    Base(){};
    virtual void Show(){cout<<"This is Base calss";}
};
class Derived:public Base
{
public:
    Derived(){};
    void Show(){cout<<"This is Derived class";}
};
int main()
{    
    //这是第一种情况
    Base* base = new Derived;
    if(Derived *der= dynamic_cast<Derived*>(base))
    {
        cout<<"第一种情况转换成功"<<endl;
        der->Show();
        cout<<endl;
    }
    //这是第二种情况
    Base * base1 = new Base;
    if(Derived *der1 = dynamic_cast<Derived*>(base1))
    {
        cout<<"第二种情况转换成功"<<endl;
        der1->Show();
    }
    else 
    {
        cout<<"第二种情况转换失败"<<endl;
    }
    delete(base);//new与delete要配对使用
    delete(base1);
    system("pause");
}

运行结果:      在这里插入图片描述
3.dynamic_cast和引用类型

 	Derived c;
    Derived & der2= c;
    Base & base2= dynamic_cast<Base&>(der2);//向上转换,安全
    base2.Show();

与指针不同的是,并不存在空引用,所以引用的dynamic_cast检测失败时会抛出一个bad_cast异常

int main()
{    
    //第一种情况,转换成功
    Derived b ;
    Base &base1= b;
    Derived &der1 = dynamic_cast<Derived&>(base1);
    cout<<"第一种情况:";
    der1.Show();
    cout<<endl;

    //第二种情况
    Base a ;
    Base &base = a ;
    cout<<"第二种情况:";
    try{
        Derived & der = dynamic_cast<Derived&>(base);
    }
    catch(bad_cast)
    {
        cout<<"转化失败,抛出bad_cast异常"<<endl;
    }
    system("pause");
}

运行结果:
在这里插入图片描述
4.static_cast静态类型转换
效果和C风格的强制类型转换是一样的

  double a = 1.999;
  void * vptr = & a;
  double * dptr = static_cast<double*>(vptr);
  cout<<*dptr<<endl;//输出1.999

static_cast也可以用在于基类与派生类指针或引用类型之间的转换。然而它不做运行时的检查,不如dynamic_cast安全。。static_cast仅仅是依靠类型转换语句中提供的信息来进行转换,而dynamic_cast则会遍历整个类继承体系进行类型检查,因此dynamic_cast在执行效率上比static_cast要差一些。

class ANIMAL
{
public:
    ANIMAL():_type("ANIMAL"){};
    virtual void OutPutname(){cout<<"ANIMAL";};
private:
    string _type ;
};
class DOG:public ANIMAL
{
public:
    DOG():_name("大黄"),_type("DOG"){};
    void OutPutname(){cout<<_name;};
    void OutPuttype(){cout<<_type;};
private:
    string _name ;
    string _type ;
};
int main()
{
    //基类指针转为派生类指针,且该基类指针指向基类对象。
    ANIMAL * ani1 = new ANIMAL ;
    DOG * dog1 = static_cast<DOG*>(ani1);
    //dog1->OutPuttype();//错误,在ANIMAL类型指针不能调用方法OutPutType();在运行时出现错误。
    //基类指针转为派生类指针,且该基类指针指向派生类对象,
    ANIMAL * ani3 = new DOG;
    DOG* dog3 = static_cast<DOG*>(ani3);
    dog3->OutPutname(); //正确

    //子类指针转为父类指针
    DOG *dog2= new DOG;
    ANIMAL *ani2 = static_cast<DOG*>(dog2);
    ani2->OutPutname(); //正确,结果输出为大黄
    //
    system("pause");
}

5.const_cast去除const属性
6.reinterpret_cast 运算符并不会改变括号中运算对象的值,而是对该对象从位模式上进行重新解释,指针类型会教导编译器如何解释某个特定地址中的内存内容及其大小

#include <iostream>
using namespace std;
int main(int argc, char** argv)
{
	int num = 0x00636261;//用16进制表示32位int,0x61是字符'a'的ASCII码
	int * pnum = &num;
	char * pstr = reinterpret_cast<char *>(pnum);
	cout<<"pnum指针的值: "<<pnum<<endl;
	cout<<"pstr指针的值: "<<static_cast<void *>(pstr)<<endl;//直接输出pstr会输出其指向的字符串,这里的类型转换是为了保证输出pstr的值
	cout<<"pnum指向的内容: "<<hex<<*pnum<<endl;
	cout<<"pstr指向的内容: "<<pstr<<endl;
	return 0;
}

在这里插入图片描述
使用reinterpret_cast运算符把pnum从int转变成char类型并用于初始化pstr后,pstr也指向num的内存区域,但是由于pstr是char类型的,通过pstr读写num内存区域将不再按照整型变量的规则,而是按照char型变量规则。一个char型变量占用一个Byte,对pstr解引用得到的将是一个字符,也就是’a’。而在使用输出流输出pstr时,将输出pstr指向的内存区域的字符,那pstr指向的是一个的字符,那为什么输出三个字符呢?这是由于在输出char指针时,输出流会把它当做输出一个字符串来处理,直至遇到’\0’才表示字符串结束。对代码稍做改动,就会得到不一样的输出结果,例如将num的值改为0x63006261,输出的字符串就变为”ab”。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

证券服务应用评测系列:海通e海通财发布9.0版本,探索证券APP持续提升用户体验

易观分析&#xff1a;APP作为券商机构线上服务的入口&#xff0c;其活跃用户规模和运营水平在一定程度上能够体现机构战略定位、品牌运营、科技创新、用户竞争等综合实力。易观分析认为&#xff0c;如何围绕用户进行创新&#xff0c;利用技术将壁垒升高&#xff0c;打造具有品牌…

PuTTY installation directory must be on a local hard drive

putty安装问题 问题描述&#xff1a;安装时候报错&#xff0c;installation directory must be on a local hard drive 解决方案&#xff0c;无法解决。 很多人使用了这个方法解决了。但是我解决不了。 1、如果是exe类型的&#xff0c;直接右击以管理员身份运行。 2、如果是…

常用的文件类型大全(建议收藏)

文件格式格式图标格式概况mpg文件mpg是一种常见的视频格式,mpeg标准主要有以下五个,MPEG-1、MPEG-2、MPEG-4、MPEG-7及MPEG-21等。mpg有可能是基于MPEG-1(VCD)或MPEG-2torrent文件torrent文件(扩展名为.torrent)包含了一些BT下载所必须的信息,根据BitTorrent协议,文件发布者…

opencv文字旋转 putText旋转90°

文章目录● opencv文字旋转 putText旋转901. cv::getTextSize获取文字的尺寸textSize2. 设置文字图像textImg尺寸格式3. 将文字绘制在文字图像textImg上4. 对文字图像textImg进行旋转5. 在原图img上设置用来放置文字图像textImg的roi区域5.1 矩形区域roi5.2 行列范围roi6. 将文…

Swin-Unet: Unet-like Pure Transformer for Medical Image Segmentation论文解读

Swin-Unet: Unet-like Pure Transformer for Medical Image Segmentation 论文&#xff1a;[2105.05537] Swin-Unet: Unet-like Pure Transformer for Medical Image Segmentation (arxiv.org) 代码&#xff1a;HuCaoFighting/Swin-Unet: The codes for the work “Swin-Unet:…

LiveNVR监控流媒体Onvif/RTSP功能功能-支持GB35114接入国标流媒体平台接入说明

LiveNVR监控流媒体Onvif/RTSP功能功能-支持GB35114接入国标流媒体平台接入说明1、GB35114注册2、LiveNVR通过GB35114接入LiveGBS2.1、开启LiveGBS 35114功能2.2、 获取设备端证书给平台2.3、LiveGBS白名单中添加需要接入的国密设备2.4、导出LiveGBS平台端证书给设备&#xff08…

管理学实验的设计与实践结课作业

一、不同组织结构类型对组织的沟通效率会带来影响&#xff0c;这也是在组织结构设计过 程需要考虑的重要内容&#xff0c;但对于两者的关系无法准确界定。如在直线职能制的组织结构中&#xff0c;管理幅度和深度是影响是影响沟通效率的主要因素。请设计实验来验证分析直线职能制…

手动部署SQL审计平台Archery(连接mysql8.x)

安装Python和virtualenv从1.9.0版本开始&#xff0c;将不再支持python3.7及以下版本&#xff0c;手动安装也将使用3.9版本作为样例&#xff0c;移除yum安装方式# 安装依赖 yum install libffi-devel wget gcc make zlib-devel openssl openssl-devel ncurses-devel openldap-de…

分享81个PHP源码,总有一款适合您

PHP源码 分享81个PHP源码&#xff0c;总有一款适合您 下面是文件的名字&#xff0c;我放了一些图片&#xff0c;文章里不是所有的图主要是放不下...&#xff0c; 81个PHP源码下载链接&#xff1a;https://pan.baidu.com/s/18jo0nrQ6tCf-e1PAylItmQ?pwd3rxz 提取码&#xff…

Mysql之多表查询

简单测试 由于我们之前没学过多表查询 我们简单测试一下初学者认为的多表查询 SELECT * FROM emp,dept这是我们的输出结果 其实不难发现 1.返回的结果就是&#xff0c;第一张表一个个数据取出然后和第二张表所有组合 最后返回的是含有两张表的所有列 2.一共返回的记录数第一章…

【ES6篇新语法】(1)ES6介绍及常量声明、对象数组,附实例详解

【写在前面】 应一些粉丝的要求&#xff0c;整理一些ES6相关的文章&#xff0c;因此借这个岁末之际&#xff0c;给大家整理一篇ES6的相关的博客&#xff0c;不管是面试还是在实际的编程上&#xff0c;我们都常提到ES6这个词&#xff0c;可能前几年比较热门&#xff0c;希望大家…

焊接变形的原因以及防止焊接变形的措施

焊接变形的原因   在焊接过程中对焊件进行了局部的、不均匀的加热是产生焊接应力及变形的原因。焊接时焊缝和焊缝附近受热区的金属发生膨胀&#xff0c;由于四周较冷的金属阻止这种膨胀&#xff0c;在焊接区域内就发生压缩应力和塑性收缩变形&#xff0c;产生了不同程度的横向…

喜报!西门子低代码连续四年获评Gartner企业低代码应用平台魔力象限领导者

点击下载最新发布的Gartner魔力象限图™https://www.mendix.com/resources/gartner-magic-quadrant-for-low-code-application-platforms/?utm_mediumpr&utm_campaignMQ&utm_sourceMQ#formWrapper 想象一下&#xff0c;一个为持续数字化转型做好准备的组织会是什么样…

EXTI中断以及系统滴答定时器SysTick的配置和使用

前言 EXTI中断来判断按键按下 EXTI即外部中断/事件控制器&#xff0c;总共支持19个中断/事件请求。每一条中断线都有独立的使能和产生中断后的标志位。 上图可见&#xff0c;中断/时间线0-15&#xff0c;总共16条线分配给了IO&#xff0c;通过设置AFIO的AFIO_EXTICR1、AFIO_…

内核调试之Kdump的原理及配置

术语介绍生产内核&#xff08;production kernel&#xff09;&#xff1a;产品或者线上服务器当前运行的内核。捕获内核&#xff08;capture kernel&#xff09;&#xff1a;系统崩溃时&#xff0c;使用kexec启动的内核&#xff0c;该内核用于捕获生产内核当前内存中的运行状态…

【windows terminal】普通用户免密ssh登录阿里云linux服务器

创建用户 [rootxxx~]# adduser linuxcool创建密钥 使用如下命令创建密钥 [rootxxx~]# ssh-keygen -t rsa创建的密钥路径 Your identification has been saved in /root/.ssh/id_rsa. Your public key has been saved in /root/.ssh/id_rsa.pub. 将公钥导入authorized_keys&…

《Go 并发数据结构和算法实践》学习笔记 Day 2

系列文章目录 这是本周期内系列打卡文章的所有文章的目录 《Go 并发数据结构和算法实践》学习笔记 Day 1_jahentao的博客-CSDN博客 文章目录系列文章目录前言一、Skiplist是什么&#xff1f;(What)Skiplist的基本接口查找元素插入元素删除元素二、并行化改造1.并发查找2.并发删…

struts漏洞总结

目录 概述 struts2漏洞 S2-001 漏洞原理 复现 struts2漏洞 S2-005 原理 分析一下003 复现 struts2漏洞s2-007 struts2漏洞 S2-008 原理 复现 struts2漏洞 S2-009 原理 复现 struts2漏洞 S2-012 原理 复现 struts2漏洞 S2-013 原理 复现 struts2漏洞 S2-0…

闭包中的内存泄漏

一.闭包的内存泄漏 1.为什么有些AO对象就不会被销毁&#xff1f; 1&#xff09;普通函数中 上述代码在执行foo函数的时候&#xff0c;内存中的过程。 执行完foo函数之后&#xff0c;foo的函数上下文被销毁了&#xff0c;那么就不会指向foo的AO对象了。 那么AO对象也会被销毁…

格创东智蝉联入选工信部工业互联网APP优秀解决方案名单

1月13日&#xff0c;工信部发布《2022年工业互联网APP优秀解决方案名单公示》&#xff0c;由格创东智研发的 “基于深度学习技术的 AI智能检测&#xff08;天枢AI&#xff09;APP 应用解决方案”、“面向泛半导体行业的设备自动控制&#xff08;EAP&#xff09;APP解决方案”入…