Basic——C++类型转换(转型操作符详解)

news2024/11/17 5:45:33

C+转型操作符

  • 1.C语言类型转换存在的隐患
  • 2.static_cast
  • 3.const_cast
    • 介绍
    • 测试案例
  • 4.dynamic_cast
  • 5.reinterpret_cast

1.C语言类型转换存在的隐患

  1. 数据丢失:当将一个较大的数据类型转换为较小的数据类型时,可能会导致数据丢失。例如,将一个浮点数转换为整数时,小数部分将被截断,可能导致精度损失。

  2. 溢出:当将一个较大的整数转换为较小的整数类型时,如果源数据超过了目标类型的表示范围,就会发生溢出。溢出可能导致结果不符合预期,甚至产生未定义行为。

  3. 不匹配的内存布局:在进行指针类型转换时,如果转换的指针类型与目标类型的内存布局不匹配,可能导致对无效内存的访问或未定义行为。

  4. 类型违规的访问:类型转换可以用于绕过类型系统的限制,例如将一个指向不相关类型的指针强制转换为目标类型的指针。这样的转换可能导致对不匹配类型的访问,可能破坏内存安全性和引发未定义行为。

  5. 程序逻辑错误:不正确的类型转换可能导致程序逻辑错误。例如,将一个指针类型转换为另一个不兼容的指针类型,可能导致错误的内存操作或数据结构访问。

  • 总结:
    就是C语言的类型转换不会检查安全性和数据转型的合理性,甚至支持从一个结构体强转型为一个指针,但是这种转换是没有意义的,C语言并没有检查,所以C+针对相关问题做出了优化!
    下面介绍C++做的四种类型转换

2.static_cast

  • 以前C的强制类型转换格式:
    (type) expression

  • 现在C+用法:static_cast(expression)

举个例子,假设你想要将一个int转型为一个double,以强迫一个整数表达式导出一个浮点数值来。采用C旧式转型,可以这么做:

int firstNumber, secondNumber;

double result =((double)firstNumber)/secondNumber;

如果采用新的C++转型法,应该这么写:

double result = static_cast(firstNumber) /secondNumber;
这种形式十分容易被辨识出来,不论是对人类或是对工具程序而言。

  • static_cast 基本上拥有与C旧式转型相同的威力与意义,以及相同的限制。例如,你不能够利用static_cast 将一个 struct 转型为int,或将一个double转型为pointer;这些都是C旧式转型动作原本就不可以完成的任务。static cast甚至不能够移除表达式的常量性(constness),因为有一个新式转型操作符const_cast专司此职

测试:
2
C语言可以让一个结构体转换为一个 指针,而这样是不可控的也是不安全无意义的。再看C+static_cast:
3
直接就报错 !!较比C更安全!!!

3.const_cast

介绍

  • 语法格式:const_cast<目标类型>(表达式)

  • 使用
    1.去除指针或引用的常量性

const int* constPtr = new int(5);
int* mutablePtr = const_cast<int*>(constPtr);  // 去除指针的常量性,使其可修改

  1. 用于函数重载:
void processData(int* data);
void processData(const int* data);

const int num = 10;
processData(const_cast<int*>(&num));  // 调用非常量参数的函数重载

  • 需要注意的是,使用 const_cast 是一种有风险的操作,因为它允许绕过对象的常量性,并可能导致未定义行为。在使用 const_cast 时,需要注意以下事项:
  1. 只能用于去除指针或引用的常量性,而不能用于去除对象本身的常量性。
  2. 被转换的指针或引用类型必须原本指向非常量对象。
  3. 修改被声明为常量的对象可能导致不一致的行为或错误的结果。确保只在确实需要修改对象的情况下使用 const_cast。
  4. 修改被声明为常量的对象可能违反代码的预期行为和约定。在修改被声明为常量的对象之前,请确保了解代码的逻辑和设计。
  • 总之,const_cast 可以用于去除指针或引用的常量性,但需要谨慎使用。应该确保在使用 const_cast 时遵循语言规范和最佳实践,以避免潜在的问题和未定义行为。

测试案例

3

4.dynamic_cast

dynamic_cast 是 C++ 中的一个运算符,用于在类层次结构中进行安全的类型转换。它用于在运行时检查指针或引用是否可以转换为目标类型,并在转换不可行时返回一个空指针或引发一个异常

  • dynamic_cast<目标类型>(表达式)

  • 下面是 dynamic_cast 的使用注意事项:

  1. 只能用于具有多态性的类层次结构:dynamic_cast 只能用于具有虚函数的类层次结构,其中基类至少有一个虚函数。这样可以在运行时通过对象的指针或引用进行类型检查和转换。

  2. 指针转换时的安全性检查:当将指针类型转换为目标类型时,dynamic_cast 会在运行时检查指针指向的对象的实际类型是否与目标类型兼容。如果转换不可行,返回一个空指针。

  3. 引用转换时的异常处理:当将引用类型转换为目标类型时,dynamic_cast 会在运行时检查引用所引用的对象的实际类型是否与目标类型兼容。如果转换不可行,会抛出一个 std::bad_cast 异常。

  4. 只能进行向下转换或侧边转换:dynamic_cast 可以进行向下转换(从基类指针或引用到派生类指针或引用)或侧边转换(在具有公共基类的类之间进行转换)。

  5. dynamic_cast 的出现解决了在类层次结构中进行安全的转换的问题。它允许在运行时检查指针或引用的实际类型,并根据需要进行类型转换,避免了潜在的错误和未定义行为。

#include <iostream>

// 基类 Animal
class Animal {
public:
    virtual void makeSound() const = 0; // 纯虚函数,子类必须实现
};

// 派生类 Cat
class Cat : public Animal {
public:
    void makeSound() const override {
        std::cout << "Meow!" << std::endl;
    }
};

// 派生类 Dog
class Dog : public Animal {
public:
    void makeSound() const override {
        std::cout << "Woof!" << std::endl;
    }
};

int main() {
    Animal* animal1 = new Cat();
    Animal* animal2 = new Dog();

    Cat* cat = dynamic_cast<Cat*>(animal1); // 向下转换
    if (cat != nullptr) {
        cat->makeSound(); // 调用 Cat 类的函数
    }

    Dog* dog = dynamic_cast<Dog*>(animal2); // 向下转换
    if (dog != nullptr) {
        dog->makeSound(); // 调用 Dog 类的函数
    }

    delete animal1;
    delete animal2;

    return 0;
}

在上述代码中,Animal 是一个抽象基类,Cat 和 Dog 是派生自 Animal 的具体类。在 main 函数中,我们创建了一个 Cat 对象和一个 Dog 对象,并将它们分别通过基类指针指向这些对象。然后,我们使用 dynamic_cast 将基类指针转换为派生类指针,并在转换成功后调用相应的派生类函数。

通过 dynamic_cast 的使用,我们可以在运行时检查指针的实际类型,并确保进行类型转换的安全性。如果转换不可行,将得到一个空指针,可以用于进行条件判断和处理

5.reinterpret_cast

reinterpret_cast 是 C++ 中的一种类型转换运算符,用于在不同类型之间进行位级别的重新解释。它可以将一个指针或引用转换为任意其他类型的指针或引用,甚至是不相关的类型。

  • 语法 :reinterpret_cast<目标类型>(表达式)
  • 下面是使用 reinterpret_cast 的一些注意事项和使用场景:
  1. 强制类型转换:reinterpret_cast 是一种非常强制的转换,它对类型之间的关系没有要求,允许将一个类型的位模式直接解释为另一个类型的位模式。这可能导致类型违规的访问和未定义行为。

  2. 潜在的不安全性和风险:reinterpret_cast 没有运行时的安全性检查,因此使用时需要非常小心。错误的使用可能导致指针或引用的无效化、内存访问错误和未定义行为。

  3. 底层数据解释:reinterpret_cast 主要用于底层的数据操作,例如将指针或引用转换为不同的指针或引用类型,以便进行位级别的操作。

  4. 特定场景下的使用:reinterpret_cast 可能用于与 C 接口进行交互、处理底层硬件和数据结构、进行类型擦除等特定场景。但是,通常情况下应该避免使用它,因为它违反了类型系统的规则。

  5. 慎重使用:由于 reinterpret_cast 可能导致难以调试和不可预测的行为,应该慎重使用,并确保对类型转换的后果有清晰的理解。

  • reinterpret_cast 的出现主要是为了满足一些底层操作和与 C 语言接口交互的需求。它提供了一种手段,可以直接操作位级别的数据,而不必考虑类型之间的关系。但是,由于其潜在的不安全性和风险,应该避免在普通的应用程序中使用它。

  • 测试

#include <iostream>

int main() {
    int number = 42;
    void* voidPtr = reinterpret_cast<void*>(&number);  // 将 int 指针转换为 void 指针

    int* intPtr = reinterpret_cast<int*>(voidPtr);  // 将 void 指针转换为 int 指针
    std::cout << "Number: " << *intPtr << std::endl;

    return 0;
}

在上述代码中,我们将一个 int 类型的指针转换为 void* 类型的指针,然后又将 void* 指针转换回 int* 类型的指针。这样的转换是在底层的位级别上进行的,允许我们将不同类型的指针进行重新解释。然后,我们使用 int* 指针解引用,输出原始的 int 类型的值。请注意,这个示例仅用于演示 reinterpret_cast 的用法,并不是一个常见的实际应用场景。

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

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

相关文章

mac M1 安装nacos

背景 m1不支持本地安装&#xff0c;只能用docker &#xff1a; “由于 rocksdb 暂不支持 M1 平台&#xff0c;所以使用 Zulu JDK 的小伙伴们运行 Nacos 2.x 版本会报错&#xff0c;网上通用的解决方案是使用 Oracle JDK 来运行 Nacos 2.x 版本&#xff0c;但对于强迫症的我来说…

计算机网关原理、子网掩码原理(路由器、交换机)

文章目录 网关网关的历史网关的功能网关的原理相关疑问为什么用子网掩码与IP地址进行与运算来确定一个IP地址所属的子网&#xff1f;网关地址是谁定的&#xff0c;是配置路由的人随意定的吗&#xff1f;&#xff08;配置人员定的&#xff09;如何正确设置网关地址&#xff08;路…

java的断言

断言介绍 Java的断言就是一条assert 声明&#xff0c;其中包含了一个布尔表达式。 断言可以被启用或者禁用&#xff0c;默认是禁用的。 断言被启用的情况下&#xff0c;执行到断言的声明&#xff0c;就会计算布尔表达式的值。如果表达式的值为false&#xff0c;那么就会抛出一…

【Elasticsearch】安装elasticsearch

目录 安装elasticsearch 1.部署单点es 1.1.创建网络 1.2.加载镜像 1.3.运行 2.部署kibana 2.1.部署 2.2.DevTools 3.安装IK分词器 3.1.在线安装ik插件&#xff08;较慢&#xff09; 3.2.离线安装ik插件&#xff08;推荐&#xff09; 1&#xff09;查看数据卷目录 …

十三、Docker Compose使用和主要功能

学习参考&#xff1a;尚硅谷Docker实战教程、Docker官网、其他优秀博客(参考过的在文章最后列出) 目录 一、核心概念二、主要功能二、docker compose常用命令三、docker compose 案例3.1 自己写一个微服务模块3.2 用Dockerfile将上面的模块编排(不使用compose)3.3 使用compose编…

滑动平均值滤波(CODESYS ST源代码)

有关滑动平均值滤波算法的详细介绍请查看下面文章链接,这里不再赘述: 博途PLC各种平均值滤波算法对比(SCL+梯形图代码)_模拟量平均值滤波梯形图程序_RXXW_Dor的博客-CSDN博客此文会对比各种滤波算法的优劣,给出具体算法描述和测试代码算术平均值不区分原始数据的质量,特…

高阶组件/react组件复用

也可以用children模式 优化 高阶组件 组件名称相同设置组件名字 效果 解决props丢失 setstate是异步更新的 推荐语法 页面更新完后的回调函数 组件性能优化 1. 2.

WAIC2023会后记

听了3天WAIC的会&#xff0c; 大开眼界&#xff0c;算是上了堂大课。 本次参会的目的是听听AI企业信息化的想法、理论和实践。以进一步探索可能的业务场景。三天的会结束后&#xff0c;留下深刻印象的有如下几点。 大模型当道 2023这次大会的主题成了大模型&#xff0c;谈的…

超链接标签和列表标签

五、超链接标签 href: target: 行内标签&#xff0c;没有href属性和span没区别 有href不写值&#xff0c;跳转当前页面&#xff0c;即刷新效果 写完之后后端数据还没过来&#xff0c;不知道要跳转哪个页面&#xff0c;不想进行刷新页面&#xff0c;加#&#xff0c;叫锚点 回到底…

Gradle插件开发

Gradle插件开发 本文链接&#xff1a;https://blog.csdn.net/feather_wch/article/details/131623779 什么是插件&#xff1f; 开发方式 插件扩展 加固实战

[工业互联-16]:工业Windows操作系统与实时性方案

目录 第1章 Windows操作系统 1.1 简介 1.2 Windows架构 第2章 工业Windows操作系统 2.1 简介 2.2 常见的工业Windows操作系统版本 2.3 定制化工业Windows 第3章 EtherCAT实时Windows方案 3.1 实时Windows的缘由 3.2 总体框架 3.3 ROS2方案 3.4 方案1&#xff1a;使…

PXE-网络批量装机

目录 【1】安装dhcp、tftp-server、httpd、syslinux、关闭防火墙、挂载镜像 【2】配置dhcp服务 【3】配置tftp服务 【4】拷贝pxe服务器的相关文件到tftp的根目录 【5】创建pxelinux.cfg文件 【6】配置httpd 【7】Kickstart自动化文件 【8】重启所有服务 【9】验证 【1…

C#对DataGridView控件的常用操作

1998年我开始接触Powerbuilder 6.5之前&#xff0c;使用过FoxPro 2.5B和Visual Base 5&#xff0c;比较而言&#xff0c;对数据库应用的开发&#xff0c;FoxPro 2.5B对开发人员很友好&#xff0c;开发程序速度快&#xff0c;Visual Base 5则几乎没有多少的优势&#xff0c;用上…

webpack5搭建与基本配置

webpack基础构建 新建文件夹进入文件夹查看是否安装node&#xff0c;命令&#xff1a;node-v创建package.json文件&#xff0c;命令&#xff1a;npm init -y安装webpack和webpack-cli&#xff0c;&#xff08;命令自动创建出package-lock.json文件和node_modules文件夹&#x…

残差网络(ResNet) -深度学习(Residual Networks (ResNet) – Deep Learning)

在第一个基于cnn的架构(AlexNet)赢得ImageNet 2012比赛之后&#xff0c;每个随后的获胜架构都在深度神经网络中使用更多的层来降低错误率。这适用于较少的层数&#xff0c;但当我们增加层数时&#xff0c;深度学习中会出现一个常见的问题&#xff0c;称为消失/爆炸梯度。这会导…

MachineLearningWu_6_FeatureScaling

x.1 feature scale 接下俩我们将考虑数据的不一致性&#xff0c;例如有的数据的范围很大&#xff0c;可能分布在好几千&#xff0c;但是我们的weight矩阵最好是在[-1, 1]的小数&#xff0c;如果数值太大就会导致我们的weight变化也很大&#xff0c;如下面这个例子就并不好&…

编译型语言和解释型语言的区别

1.操作系统怎么识别编程语言 计算机能识别二进制数&#xff0c;但是无法识别编程语言&#xff0c;比如你把 01000001100通过相关手段输入计算机中计算机就能识别其中的含义并且执行对应的命令&#xff0c;但是你输入 print(hello world)计算机就无法识别其含义&#xff0c;这就…

基于springboot+mybatis-plus+mysql+vue音乐网站管理系统

基于springbootmybatis-plusmysqlvue音乐网站管理系统 一、系统介绍1、系统主要功能&#xff1a;2.涉及技术框架&#xff1a;3.项目说明&#xff1a; 二、功能展示三、其它系统四、获取源码 一、系统介绍 1、系统主要功能&#xff1a; 音乐播放 用户登录注册 用户信息编辑、头…

4. PS切图

4.1常见的图片格式 jpg图像格式: JPEG ( .JPG )对色彩的信息保留较好,高清,颜色较多,我们产品类的图片经常用jpg格式的gif图像格式 : GIF格式最多只能储存256色,所以通常用来显示简单图形及字体,但是可以保存透明背景和动画效果,实际经常用于一些图片小动画效果png图像格式&am…

Tomcat 线程池

目录 概述 tomcat线程池工作原理 关键源码 Connector 配置 Executor 线程配置 tomcat核心组件&#xff08;题外&#xff09; 概述 Tomcat 是一个流行的 Java Web 服务器&#xff0c;它使用线程池来处理客户端请求。线程池是一组预先创建的线程&#xff0c;用于执行并发任…