C++中的类型转换

news2024/9/23 3:12:54

文章目录

  • 一、隐式类型转换
  • 二、显式类型转换
  • 三、c++风格的类型转换


一、隐式类型转换

 
隐式类型转换,顾名思义,就是没有明显的声明要进行类型转换,隐式类型转换有可能造成数据精度的丢失,所以通常所做的类型转换都是从size小的数据到size大的数据。
 
我们以数字为例,在程序中见到的所有整形立即数都被当作int类型,所有浮点数立即数都被当作double类型,如下所示:

int main() {
    auto a = 12.34;
    auto b = 100;
    std::cout << typeid(a).name() << std::endl; //double
    std::cout << typeid(b).name() << std::endl; //int
    return 0;
}

在进行加减乘除等基本运算的时候,首先要保证运算符两边是同类型的数据,这时候,编译器会做隐式的类型转换,都是将数据从size小转到size大,这时不会损失数据精度,⚠️同时存在signedunsigned的时候,signed会转换成unsigned。其他的转换借鉴下图:
在这里插入图片描述
对象中包含的隐式转换:

  1. 对象构造的时候使用如果编译器可以找到对象的构造函数,此时也会发生隐式的类型转换,但是通常不希望这种情况发生,可以在构造函数前加explicit关键字进行避免;

 

二、显式类型转换

这个没什么好说的,通过类型强转的方式,程序上能直接指定要转换成何种类型。但是需要注意一点的是,对象也能通过运算符重载函数强转成基本类型。使用方法如下:

class A {
public:
    explicit A(int ma) : _ma(ma) {

    }
    explicit operator double() const {
        double a = 13.34;
        return a;
    }
private:
    int _ma;
};

 

三、c++风格的类型转换

  1. static_cast
    static_cast类似于强制类型转换,只是是一种tight type check的类型转换,而且是编译时期的类型转换。之所以说他是tight type check是因为static_cast不允许做一些不合理的类型转换,如下所示:
#include <iostream>
#include <iostream>
using namespace std;
int main()
{
    int a = 10;
    char c = 'a';
  
    // pass at compile time, may fail at run time
    int* q = (int*)&c;  //clang编译通过
    int* p = static_cast<int*>(&c); //编译失败
    return 0;
}

另外在继承结构中,必须是public继承才能使用static_cast进行类型向上转换,如下所示:

class Base {
};

class Derived : private Base { // Inherited private/protected not public
};

int main() {
    Derived d1;
    Base *b1 = (Base *) (&d1); // allowed
    Base *b2 = static_cast<Base *>(&d1); //编译失败
    return 0;
}

 
2. dynamic_cast
这种转换需要用到RTTI机制,关于RTTI的原理和对象内存布局,见我的另一篇博客C++对象内存布局。
在这里插入图片描述

既然涉及到RTTI,那就必须有虚函数,如果继承结构中没有虚函数,那也就用不了dynamic_cast,dynamic_cast支持downcasting和upcasting,但是指针必须指向的是同一个对象,如果转换失败,dynamic_cast返回nullptr。使用方法如下:

// C++ program demonstrate if there
// is no virtual function used in
// the Base class
#include <iostream>
using namespace std;

// Base class declaration
class Base {
	void print()
	{
		cout << "Base" << endl;
	}
};

// Derived Class 1 declaration
class Derived1 : public Base {
	void print()
	{
		cout << "Derived1" << endl;
	}
};

// Derived class 2 declaration
class Derived2 : public Base {
	void print()
	{
		cout << "Derived2" << endl;
	}
};

// Driver Code
int main()
{
	Derived1 d1;

	// Base class pointer hold Derived1
	// class object
	Base* bp = dynamic_cast<Base*>(&d1);

	// Dynamic casting
	Derived2* dp2 = dynamic_cast<Derived2*>(bp);
	if (dp2 == nullptr)
		cout << "null" << endl;

	return 0;
}

 
3. reinterpret_cast
顾名思义,重新解释的意思,这种类型转换将任意一种指针转换成另一种指针,这是一种危险的转换,使用方式如下:

#include <iostream>
using namespace std;
 
int main()
{
    int* p = new int(65);
    char* ch = reinterpret_cast<char*>(p);
    cout << *p << endl;
    cout << *ch << endl;
    cout << p << endl;
    cout << ch << endl;
    return 0;
}

 
4. const_cast
const_cast用于将变量的const约束去掉,const_cast并不像想象的那样可以直接修改const变量,const_cast去除掉的一般是指针的约束,使用方法见下:

const int a=10;
int b  = const_cast<int>(a); //这里会编译失败,因为实际上a的const限制是无法去除的
int main(void) {
    int a1 = 40;
    const int *b1 = &a1;
    int *c1 = const_cast <int *> (b1); 
    *c1 = 100;   //此处没有问题,可以通过c1修改a1;
    *b1 = 1000; //此处编译失败,不能通过b1修改a1;
    cout << a1 << endl;
    return 0;
}

如上所示,a1并不是const变量,只是我们定义了一个const指针,我们不能通过这个指针修改a1,但是我们可以把指针的const去掉,然后用去掉const限制的指针来修改a1。
 
const_cast还可以用来在类的const函数中修改成员变量,因为在const方法中的this指针实际上是一个const指针,我们可以用const_cast去掉const限制,然后来修改成员变量,使用方法如下所示:

class student
{
private:
    int roll;
public:
    // constructor
    student(int r):roll(r) {}
  
    // A const function that changes roll with the help of const_cast
    void fun() const
    {
        ( const_cast <student*> (this) )->roll = 5;
    }
  
    int getRoll()  { return roll; }
};

const_cast是一种比强转更安全的类型转换,比如将const int* 转为int是允许的,但是将const int转为char*是不允许的。
const_cast还可以将volatile约束去掉,如下所示:

int main(void)
{
    int a1 = 40;
    const volatile int* b1 = &a1;
    cout << "typeid of b1 " << typeid(b1).name() << '\n'; //PVKi
    int* c1 = const_cast <int *> (b1);
    cout << "typeid of c1 " << typeid(c1).name() << '\n'; //Pi
    return 0;
}

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

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

相关文章

哈夫曼编码(Huffman coding)

哈夫曼编码哈夫曼编码简介发展历史思想示例不足哈夫曼编码 简介 哈夫曼编码(Huffman Coding)&#xff0c;又称霍夫曼编码&#xff0c;是一种编码方式&#xff0c;哈夫曼编码是可变字长编码(VLC)的一种。Huffman于1952年提出一种编码方法&#xff0c;该方法完全依据字符出现概…

[附源码]JAVA毕业设计计算机在线学习管理系统-(系统+LW)

[附源码]JAVA毕业设计计算机在线学习管理系统-&#xff08;系统LW&#xff09; 目运行 环境项配置&#xff1a; Jdk1.8 Tomcat8.5 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项…

实现自定义Spring Boot Starter

实现自定义Spring Boot Starter一、原理二、实战1 自定义 Spring Boot Starter1.1 添加maven依赖1.2 属性类AuthorProperties1.3 自动配置类AuthorAutoConfiguration1.4 业务逻辑AuthorServer1.5 spring.factories2 测试自定义的 Spring Boot Starter2.1 新建module或者新建工程…

什么软件能识别软件?学会这几个软件就可以了

在日常学习或工作中&#xff0c;我们经常会因为各种各样的原因&#xff0c;导致资料无法记全。比如上课的时候老师讲课速度过快、或者开会时需要整理的资料太多&#xff0c;我们做不到一心二用&#xff0c;边听边记。你们遇到类似情况的时候&#xff0c;都是怎么解决的呢&#…

0x02. Spring Boot 3 之SpringBoot 版本升级最佳实践指南

Spring Boot 3 之SpringBoot低版本升级最佳实践0x01 前言0x02 升级Spring Boot2.1 从Spring Boot 1.5.x 升级到Spring Boot 2.x2.1.1 依赖检查2.1.2 检查自定义配置2.1.3 检查系统需要2.1.4 升级到Spring Boot 2.x2.1.5 配置属性迁移2.2 从Spring Boot 2.7.x 升级到Spring Boot…

概率统计·样本及抽样分布【随机样本、抽样分布】

总体与个体 总体&#xff1a;试验的全部可能的观察值称为总体 个体&#xff1a;总体中每个可能的观察值称为个体 总体期望样本平均期望 总体方差/n样本平均方差 随机样本 X1&#xff0c;X2……Xn相互独立&#xff08;x1&#xff0c;x2……xn是观察值&#xff09;&#xff0…

[附源码]计算机毕业设计springboot疫苗及注射管理系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

STC 51单片机52——自发自收串行通信

#include <reg52.h> unsigned char ch0; /* 初始化函数 */ void uart_init() { TMOD0x20; //T1为方式2 TL10xfd; TH10xfd; //波特率为9600的计数初值 SCON0x50; //串口工作在方式1。允许接收 …

[附源码]Python计算机毕业设计Django基于Java的日用品在线电商平台

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…

五问补盲(一) | 激光雷达补盲,视场多大算大?

作者 | 爱LiDAR的小飞哥 编辑 | 王博“大&#xff01;超大&#xff01;更大&#xff01;” 最近&#xff0c;补盲激光雷达市场热闹非凡&#xff0c;各家在宣传产品的视场角时竭尽全力&#xff0c;毫不吝啬形容词。 回归到实际需求&#xff0c;多大的视场角够用&#xff1f;超大…

西门子触摸屏上电显示初始画面几秒后,自动切换到下一个画面的具体方法

西门子触摸屏上电显示初始画面几秒后,自动切换到下一个画面的具体方法 例如:在启动画面停留10秒后,切换到其他画面。 具体实现方法可参考以下内容: 如下图所示,新建一个项目,在画面中添加2个画面, 如下图所示,在变量中添加一个内部变量tag1,用于控制画面的切换, …

es查询响应结果中获取某些字段的值

有时候使用es查询出的结果包含多个字段&#xff0c;如果数据中仅仅包含几个字段时&#xff0c;我们是很容易挑出自己需要的字段值&#xff0c;但是如果数据中包含几十或者几百甚至更多时&#xff0c;尤其是数据中嵌套好多层时&#xff0c;不容易直接挑取出需要的值&#xff0c;…

【人工智能/算法】搜索求解(Solving Problems by Searching)

文章目录一、求解与搜索二、盲目式搜索1. 深度优先搜索&#xff08;Depth First Search, DFS&#xff09;回溯搜索&#xff08;Backtracking Search&#xff09;2. 广度优先搜索&#xff08;Breadth First Search, BFS&#xff09;一致代价搜索&#xff08;Uniform-cost Search…

你们看过《点燃我,温暖你》没有呀,里面比较火的那个爱心代码,今天小编用Python实现啦,这就是程序员的烂漫吗

前言 包子们&#xff0c;上午好 最近有个剧挺火的 就是那个程序员的剧&#xff0c;叫《点燃我&#xff0c;温暖你》 最近听说很火呀&#xff0c;那作为程序员&#xff0c;Python中的战斗机的小编&#xff0c;能不给大家安排一波&#xff01; 怎么说呢&#xff0c;用这个表白也…

DJ13-1 汇编语言程序设计-1

目录 一、基本概念 1. 机器语言&#xff08;machine language&#xff09; 2. 汇编语言&#xff08;assembly language&#xff09; 3. 汇编语言源程序 4. 汇编&#xff08;assemble&#xff09; 5. 汇编程序&#xff08;assembler&#xff09; 6. 宏汇编程序&#xff0…

[附源码]JAVA毕业设计教材管理(系统+LW)

[附源码]JAVA毕业设计教材管理&#xff08;系统LW&#xff09; 目运行 环境项配置&#xff1a; Jdk1.8 Tomcat8.5 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xf…

利用CMOS数字隔离器提高智能计量解决方案的数据完整性和可靠性

介绍 随着消费者从传统的机电电表升级到联网的智能电表&#xff0c;自动读表&#xff08;AMR&#xff09;市场预计在未来几年将以两位数的速度增长。当今先进的智能电表使用最新的集成电路&#xff08;IC&#xff09;技术来准确地测量和报告所消耗的耗电量。虽然智能电表比机电…

【pen200-lab】10.11.1.231

pen200-lab 学习笔记 【pen200-lab】10.11.1.231 &#x1f525;系列专栏&#xff1a;pen200-lab &#x1f389;欢迎关注&#x1f50e;点赞&#x1f44d;收藏⭐️留言&#x1f4dd; &#x1f4c6;首发时间&#xff1a;&#x1f334;2022年11月27日&#x1f334; &#x1f36d;作…

Metabase学习教程:系统管理-2

数据共享指南 在组织内部或外部&#xff0c;共享数据或分析的选项是什么&#xff1f;何时应该使用一种方法而不是另一种方法&#xff1f; 你有数据&#xff0c;你想&#xff08;或被要求&#xff09;分享它。这些数据是一个问题还是一个访问多个数据库完整的问题数据资料室&a…

SpringCloud - Sentinel熔断与限流

文章目录一.Sentinel下载安装运行二.Sentinel初始化监控三.流控规则1. 阈值类型1.1 QPS1.2 线程数2. 流控模式2.1 直接2.2 关联2.3 链路3. 流控效果3.1 快速失败3.2 WarmUp预热3.3 排队等待四.降级规则1. RT2. 异常比例3. 异常数五.Sentinel 热点key1. 基本使用2. 参数例外项六…