C++四种类型转换操作符 static_cast、dynamic_cast、reinterpret_cast、const_cast介绍

devtools/2024/11/24 19:21:19/

前言

  • C风格的强制类型转换很简单,都可以使用Type b = (Type)a形式转换。但这种方式存在一些缺点,比如信息丢失或精度损失,代码可读性的下降等。
  • 因此C++提供了四种类型转换符来应对不同场合。分别是static_castdynamic_castreinterpret_castconst_cast

四种类型比较

类型转换符用途特点
static_cast用于相关类型之间的转换
如基本数据类型之间的转换
派生类指针或引用转为基类指针或引用(上行转换)(总是安全的)
基类指针或引用转为派生类指针或引用(下行转换)(结果可能未定义)
编译时检查类型兼容性
适用于相关类型之间的转换
dynamic_cast主要用于基类和派生类之间的转换,会进行类型检查,
因此上行转换和上行转换都是安全的
运行时检查类型兼容性
适用于多态对象之间的转换
reinterpret_cast主要用于指针或引用类型之间的转换
指针与整型数据之间的转换
不进行类型检查,只是简单地重新解释数据的二进制表示
高风险,容易导致未定义行为
const_cast用于添加或移除变量的 const 或 volatile 属性用于添加或移除 const 或 volatile 属性
不影响其他类型属性

四种类型详细介绍

static_cast

  • 静态类型转换,类似C风格的强制转换。
  • 可以进行基本数据类型的转换,enumstructintcharfloatlong等。
    •   int data = 10010;char cData = static_cast<char>(data);
      
  • 不能转换指针类型,但是可以将指针与void*进行互转。
    •   	int data = 10010;int *pData = &data;long *plData = static_cast<long*>(pData);  // 不允许转换
      
    •   	int data = 10010;int *pData = &data;void *pvData = static_cast<void*>(pData);  // 可以转换long *plData = static_cast<long*>(pvData); // 可以转换
      
  • 不能用于两个不相关类型的转换,比如将int*转为int
    •   	int data = 10010;int *p1 = &data;int num = static_cast<int>(p1);  //不允许转换
      
  • 从派生类指针或引用转换为基类指针或引用(上行转换)时,static_cast总是安全的。
    •   class Animal {public:virtual void cry() {std::cout << "Animal cry..." << std::endl;}virtual ~Animal() {}};class Dog :public Animal {public:void cry() override {std::cout << "Dog cry..." << std::endl;}void print() {std::cout << "I am dog" << std::endl;}};int main() {Dog* pDog = new Dog;// 子类转为父类是安全的Animal* pAnimal = static_cast<Animal*>(pDog);// 调用子类的cry方法pAnimal->cry();return 0;}
      
  • 从基类指针或引用转换为派生类指针或引用(下行转换)时,static_cast可以工作,但前提是必须确保基类指针实际上指向的是派生类对象。否则,结果将是未定义的。
    •   class Animal {public:virtual void cry() {std::cout << "Animal cry..." << std::endl;}virtual ~Animal() {}};class Dog :public Animal {public:void cry() override {std::cout << "Dog cry..." << std::endl;}};class Cat :public Animal {public:void cry() override {std::cout << "Cat cry..." << std::endl;}};int main() {Animal* pAnimal = new Dog;Dog* pDog = static_cast<Dog*>(pAnimal);pDog->cry();   // 这里调用Dog的方法,是正常的Cat* pCat = static_cast<Cat*>(pAnimal);pCat->cry();   // 这里仍然调用Dog的方法,是不正确的return 0;}
      

dynamic_cast

  • 动态类型转换。是一种运行时类型检查的强制类型转换操作符,主要用于处理基类与派生类之间的转换。
  • 如果是指针类型转换失败,会返回空,如果是引用类型转换失败,会抛出一个bad_cast异常。
  • 从派生类指针或引用转换为基类指针或引用(上行转换)。
    •   class Animal {public:virtual void cry() {std::cout << "Animal cry..." << std::endl;}virtual ~Animal() {}};class Dog :public Animal {public:void cry() override {std::cout << "Dog cry..." << std::endl;}void print() {std::cout << "I am dog" << std::endl;}};int main() {Dog* pDog = new Dog;// 子类转为父类Animal* pAnimal = dynamic_cast<Animal*>(pDog);// 调用子类的cry方法pAnimal->cry();return 0;}
      
  • 从基类指针或引用转换为派生类指针或引用(下行转换)。
    •   class Animal {public:virtual void cry() {std::cout << "Animal cry..." << std::endl;}virtual ~Animal() {}};class Dog :public Animal {public:void cry() override {std::cout << "Dog cry..." << std::endl;}};class Cat :public Animal {public:void cry() override {std::cout << "Cat cry..." << std::endl;}};int main() {Animal* pAnimal = new Dog;// 父类转为子类, 会进行类型检查// 这里会转换成功Dog* pDog = dynamic_cast<Dog*>(pAnimal);if (pDog == NULL) {std::cout << "pDog is null" << std::endl;return -1;}pDog->cry();   Cat* pCat = dynamic_cast<Cat*>(pAnimal);// 这里会转换失败if (pCat == NULL) {std::cout << "pCat is null" << std::endl;return -1;}pCat->cry();return 0;}
      

const_cast

  • 主要用于去除const属性。直接看一个示例
    •   int main() {int data = 10010;const int* pcData = &data;// 这样是无法修改的 //*pcData = 10020;// 可转为int*修改int* pData = const_cast<int*>(pcData);*pData = 10020;// 打印结果都为10020std::cout << "data: " << data << std::endl;std::cout << "*pcData: " << *pcData << std::endl;std::cout << "*pData: " << *pData << std::endl;return 0;}
      

reinterpret_cast

  • 主要用于指针类型或者引用类型之间的转换。
  • 将一个指针类型转为另一个指针类型
    •   	int data = 10010;int *pData = &data;char *pCh = reinterpret_cast<char*>(pData);
      
  • 将一个引用类型转为另一个引用类型
    •   	int iData = 10010;int &pData = iData;char &cData = reinterpret_cast<char&>(pData);
      
  • 指针与整型数据之间的转换。
    •   	int iData = 10010;char cData = 10;long long lData = 678290;// 结果可能未定义char *pCh = reinterpret_cast<char*>(iData);pCh = reinterpret_cast<char*>(cData);pCh = reinterpret_cast<char*>(lData);
      
  • 不允许进行基本类型的转换
    •   	int iData = 10010;// 不允许char cData = reinterpret_cast<char>(iData);
      
  • 注意事项
    • 使用 reinterpret_cast进行不合适的转换可能会导致未定义行为。
    • reinterpret_cast的行为可能依赖于具体的硬件和编译器实现。因此,使用 reinterpret_cast编写的代码可能不具备良好的可移植性。
    • 尽量避免使用 reinterpret_cast,除非确实需要低级别的控制。大多数情况下,使用 static_castdynamic_cast更为安全和合适。
    • reinterpret_cast不提供任何类型的检查,因此使用时必须确保转换是合理的。

http://www.ppmy.cn/devtools/136621.html

相关文章

linux通过手工删除文件卸载oracle 11g rac的具体步骤

在linux操作系统中&#xff0c;有些时候我们自己学习和测试会临时搭建的oracle rac。事情完成后&#xff0c;我们想回收资源&#xff0c;需要去卸载oracle rac。为了快速卸载oracle rac&#xff0c;今天我们介绍下如何通过手工删除文件的方式来完成工作&#xff08;操作都需要在…

(免费送源码)计算机毕业设计原创定制:Java+JSP+HTML+JQUERY+AJAX+MySQL springboot计算机类专业考研学习网站管理系统

摘 要 大数据时代下&#xff0c;数据呈爆炸式地增长。为了迎合信息化时代的潮流和信息化安全的要求&#xff0c;利用互联网服务于其他行业&#xff0c;促进生产&#xff0c;已经是成为一种势不可挡的趋势。在大学生在线计算机类专业考研学习网站管理的要求下&#xff0c;开发一…

从0-1逐步搭建一个前端脚手架工具并发布到npm

前言 本文介绍的案例已同步到github&#xff0c;github地址。 vue-cli 和 create-react-app 等 cli 脚手架工具用于快速搭建应用&#xff0c;无需手动配置复杂的构建环境。本文介绍如何使用 rollup 搭建一个脚手架工具。 脚手架工具的工作流程简言为&#xff1a;提供远端仓库…

《筑牢安全防线:培养 C++安全编程思维习惯之道》

在当今数字化飞速发展的时代&#xff0c;软件安全的重要性已提升到前所未有的高度。C作为一种广泛应用于系统开发、游戏制作、高性能计算等众多领域的编程语言&#xff0c;其程序的安全性更是关乎重大。培养 C安全编程的思维习惯&#xff0c;不仅是开发者个人能力提升的关键&am…

蓝桥杯每日真题 - 第21天

题目&#xff1a;(空间) 题目描述&#xff08;12届 C&C B组A题&#xff09; 解题思路&#xff1a; 转换单位&#xff1a; 内存总大小为 256MB&#xff0c;换算为字节&#xff1a; 25610241024268,435,456字节 计算每个整数占用空间&#xff1a; 每个 32 位整数占用…

使用ENSP实现NAT

一、项目拓扑 二、项目实现 1.路由器AR1配置 进入系统试图 sys将路由器命名为R1 sysname R1关闭信息中心 undo info-center enable进入g0/0/0接口 int g0/0/0将g0/0/0接口IP地址配置为12.12.12.1/30 ip address 12.12.12.1 30进入e0/0/1接口 int g0/0/1将g0/0/1接口IP地址配置…

应急响应靶机——linux2

载入虚拟机&#xff0c;打开虚拟机&#xff1a; 居然是没有图形化界面的那种linux&#xff0c;账户密码&#xff1a;root/Inch957821.&#xff08;注意是大写的i还有英文字符的.&#xff09; 查看虚拟机IP&#xff0c;192.168.230.10是NAT模式下自动分配的 看起来不是特别舒服&…

法语旅游常用口语-柯桥学外语到蓝天广场泓畅学校

以下是一些实用的法语旅游常用口语&#xff0c;帮助你在法国旅行时能够进行基本的交流&#xff1a; 问候与道别 Bonjour: 用于日常问候。Au revoir: 用于告别。 请求帮助 S’il vous plat: 用于请求帮助&#xff0c;例如在需要寻找某个地点或服务时。 询问信息 Excusez-moi: 用…