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

C++四种cast使用详细介绍

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

北京

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

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

看不清楚,换张图片

免费获取短信验证码

C++四种cast使用详细介绍

在C++中,我们经常使用到类型的转换,像把一个int类型转换成char类型,一个int类型转换成double类型,这些转换属于隐式类型转换。而今天我们要来讲的是显式类型转换。C++提供了四种显式类型转换,分别是:static_cast、dynamic_cast、const_cast、reinterpret_cast

一、static_cast

static_cast的定义为:

static_cast<type_name>(expression)

type_name是转换的类型,expression是被转换的对象或者表达式。

static_cast一般用于隐式转换,当type_name和express至少有一方可以隐式转换时,则可以用static进行强制类型转换。可以用于常见的int、float、double等类型转换;转换成功返回true,否则返回false(相当于C语言中的强制类型转换)。

1、基本数据类型转换

double serven_double_1 = 1.2;
std::cout<<serven_double_1<<std::endl;
 
int serven_int_1 = static_cast<int>(serven_double_1);
std::cout<<serven_int_1<<std::endl;
 
double serven_double_2 = static_cast<double>(serven_int_1);
std::cout<<serven_double_2<<std::endl;

运行结果:基本类型的转换,可以看到double类型转换成int类型后丢失了精度,这一点跟reinterpret_cast不一样,reinterpret_cast是底层二进制的强制拷贝和语义转换,所以不会丢失精度,后面会讲到。

2、指针和void指针的转换

int* serven_int_2 = new int(2);
void * serven_void_1 = static_cast<void*>(serven_int_2);
int *serven_int_3 = static_cast<int*>(serven_void_1);
*serven_int_2 = 6;
 
std::cout<<*serven_int_2<<std::endl;
std::cout<<*serven_int_3<<std::endl;
std::cout<<serven_void_1<<std::endl;
std::cout<<serven_int_2<<std::endl;
std::cout<<serven_int_3<<std::endl;

 运行结果:void指针和其他类型的指针进行转化的时候,他们都是指向同一个地址。

 3、父类和子类之间的转换

class SERVEN_PARENT{
public:
    SERVEN_PARENT(){}
    void Function(){
        std::cout<<"PARENT"<<std::endl;
    }
};
 
class SERVEN_CHILD : public SERVEN_PARENT{
public:
    SERVEN_CHILD(){}
    void Function(){
        std::cout<<"CHILD"<<std::endl;
    }
};
 
 
void main(){
 
    SERVEN_PARENT* ser_par = new SERVEN_PARENT();
    ser_par->Function();
    SERVEN_CHILD* ser_chi = static_cast<SERVEN_CHILD*>(ser_par);
    ser_chi->Function();
 
}

运行结果:在main函数第二行中定义了一个ser_chi,是一个派生类对象,然后强制将基类对象转换成子类,这种叫做下行转换,转换后打印的结果是子类的Function,使用static_cast来进行向下转换是不安全的,因为当子类中定义了基类没有的变量,并且在Function函数中使用了这个变量,那么程序将会报错。

 下面我们来看一下static_cast不安全的例子:

class SERVEN_PARENT{
public:
    SERVEN_PARENT(){}
    void Function(){
        std::cout<<"PARENT"<<std::endl;
    }
};
 
class SERVEN_CHILD : public SERVEN_PARENT{
public:
    SERVEN_CHILD(){}
    void Function(){
        std::cout<<"CHILD"<<std::endl;
        std::cout<<nums<<std::endl;
    }
 
private:
    char nums = 'g';
};
 
 
void main(){
 
    SERVEN_PARENT* ser_par = new SERVEN_PARENT();
    ser_par->Function();
    SERVEN_CHILD* ser_chi = static_cast<SERVEN_CHILD*>(ser_par);
    ser_chi->Function();
 
}

 运行结果:因为派生类对象使用了自己独有的变量,所以打印char字符的时候就出现了乱码。

二、dynamic_cast

dynamic_cast的定义为:

dynamic_cast<type_name>(expression)

type_name是转换的类型,expression是被转换的对象或者表达式。

dynamic一般用于基类指向派生类时的强制转换,转换成功返回true,失败返回false。它不像static_cast一样向下转换不安全,它是安全的。它的安全性体现在RTTI,那什么是RTTI呢?
RTTI是运行时类型识别。程序能够使用基类的指针或引用来检查着这些指针或引用所指的对象的实际派生类型(判断指针原型)。RTTI提供了两个非常有用的操作符:typeid和dynamic_cast。(三个最主要的东西,dynamic_cast,typeid,type_info)。typeid:typeid函数(为type_info类的友元函数,为什么要这样呢?目的是防止创建type_info对象)的主要作用就是让用户知道当前的变量是什么类型的,它可以返回一个type_info的引用,可以获取类的名称和编码typeid重载了type_info中的==和!=可以用于判断两个类型是否相等。
dynamic_cast和static_cast在类继承的区别就是dynamic_cast向下转换是安全的。

三、const_cast

const_cast的定义为:

const_cast<type_name>(expression)

type_name是转换的类型,expression是被转换的对象或者表达式。

const_case有两个功能,分别是去掉const和加上const,一般用于去掉const,修改被const修饰为常量的值。但是修改的这个值本身不能是const常量,而是被二次引用或者传参数时被引用为const,才能修改,否则修改失败。同时type和express两个类型要一直去掉const,修改成功返回true,否则返回false。

1、加上const

int* serven_int_4 = new int(2);
const int* serven_int_5 = const_cast<const int*>(serven_int_4);     // 转换为常量指针
*serven_int_4 = 3;
//*serven_int_5 = 4;              // 不能修改
std::cout<<*serven_int_4<<std::endl;
std::cout<<*serven_int_5<<std::endl;
std::cout<<serven_int_4<<std::endl;
std::cout<<serven_int_5<<std::endl;

2、去掉const

(1)const修饰指针,指针指向一个类对象(常量指针)

将一个常量指针转换成非常量指针。

class SERVEN_PARENT{
public:
    SERVEN_PARENT(){}
    void Function(){
        std::cout<<"PARENT"<<std::endl;
    }
};
 
class SERVEN_CHILD : public SERVEN_PARENT{
public:
    SERVEN_CHILD(){}
    void Function(){
        std::cout<<"CHILD"<<std::endl;
        std::cout<<nums<<std::endl;
    }
 
private:
    char nums = 'g';
};
 
void main(){
    SERVEN_PARENT ser_par;
    const SERVEN_PARENT* pP = &ser_par;
    SERVEN_PARENT* pP_1 = const_case<SERVEN_PARENT*>(pP);    // 强制将pP转换成非const
    
}

(2)const修饰指针指向对象的数值(指针常量)

将指针常量转换为非指针常量。

void main(){
    SERVEN_PARENT ser_par;
    SERVEN_PARENT* const pP = &ser_par;
    SERVEN_PARENT* pP_1 = const_case<SERVEN_PARENT*>(pP);    // 强制将pP转换成非const
    
}

(3)const修饰指针指向对象的数值并且修饰指针(常量指针常量)

常量指针常量可以被转换为非常量指针常量,也可以转换成指针常量或者常量指针。

void main(){
    SERVEN_PARENT ser_par;
    const SERVEN_PARENT* const pP = &ser_par;
    SERVEN_PARENT* pP_1 = const_cast<SERVEN_PARENT*>(pP);    // 强制将pP转换成非const
    const SERVEN_PARENT* pP_2 = const_cast<SERVEN_PARENT*>(pP);    // 强制将pP转换成常量指针
    SERVEN_PARENT* const pP_2 = const_cast<SERVEN_PARENT*>(pP);    // 强制将pP转换成指针常量
 
    
}

四、reinterpret_cast

reinterpret_cast的定义为:

reinterpret_cast<type_name>(expression)

type_name是转换的类型,expression是被转换的对象或者表达式。

reinterpret_cast是一种比较粗暴的转换方式,并且是最不安全的,为什么说它粗暴呢?因为它直接去拷贝最底层的二进制,它的本质是编译器的指令,它的作用是可以把一个指针转换成一个整数,也可以把一个整数转换成一个指针。或者不同类型的指针相互转换。

double serven_double_2 = 1.20;
char* serven_char_1 = reinterpret_cast<char* >(&serven_double_2);
double* serven_double_3 = reinterpret_cast<double*>(serven_char_1);
std::cout<<*serven_double_3<<std::endl;
 
int* serven_int_6 = reinterpret_cast<int*>(&serven_double_2);
double* serven_double_4 = reinterpret_cast<double*>(serven_int_6);
std::cout<<*serven_double_3<<std::endl;

运行结果:我们可以看到reinterpret_cast将double类型转换成int,再转换成double类型后精度不会丢失,而static_cast会丢失。

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

免责声明:

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

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

C++四种cast使用详细介绍

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

下载Word文档

猜你喜欢

Activity 四种启动模式详细介绍

Activity 四种启动模式详细介绍在Android中每个界面都是一个Activity,切换界面操作其实是多个不同Activity之间的实例化操作。在Android中Activity的启动模式决定了Activity的启动运行方式。Andr
2023-05-31

C++BoostMultiIndex使用详细介绍

Boost是为C++语言标准库提供扩展的一些C++程序库的总称。Boost库是一个可移植、提供源代码的C++库,作为标准库的后备,是C++标准化进程的开发引擎之一,是为C++语言标准库提供扩展的一些C++程序库的总称
2022-11-13

Android LaunchMode四种启动模式详细介绍

Android LaunchMode详解 越是做的时间越长,基础知识就忘的越干净,最近做一个项目中,发现启动的几个Activity居然重叠了,我ri~~,再不回忆一下就要退出Android界了。 概念解释 Task Task叫做任务,这个简
2022-06-06

C++移动语义详细介绍使用

首先,移动语义和完美转发这两个概念是在C++的模板编程的基础上,新增的特性,主要是配合模板来使用。本篇会从C++的值类型,到移动拷贝与移动赋值来理解移动语义与完美转发
2023-01-28

fastjson 使用方法详细介绍

Fastjson介绍Fastjson是一个Java语言编写的JSON处理器。1、遵循http://json.org标准,为其官方网站收录的参考实现之一。2、功能qiang打,支持JDK的各种类型,包括基本的JavaBean、Collecti
2023-05-30

TypeScript泛型使用详细介绍

泛型是静态类型语言的基本特征,允许将类型作为参数传递给另一个类型、函数、或者其他结构。TypeScript支持泛型作为将类型安全引入组件的一种方式。这些组件接受参数和返回值,其类型将是不确定的,直到它在代码中被使用
2022-11-13

详细介绍Github的使用方法

随着互联网技术的不断发展,越来越多的开发者开始加入到开源项目中,Github作为目前全球最大的代码托管平台之一,也成为了开发者们分享、学习、合作的重要工具之一。然而,如何使用Github来进行代码管理、版本控制、协作开发等,还是很多新手开发
2023-10-22

编程热搜

  • 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动态编译

目录