当前位置: 首页 > news >正文

C++语法系列之类型转换


前言

类型转换是经常存在的情况,类型转换分为隐式类型转化 和 显式类型转化

隐式类型转化:编译器在编译阶段自动进行,能转就转,不能转就编译失败

double i = 3.3;
int b = i; //隐式类型转化 double -> int

C++搞出来了四种强制类型转换操作符,一一来介绍一下。

显式类型转化:需要用户自己处理

int *p = (int*)malloc(sizeof(int));//显示

转换当然是有问题的了

  1. 隐式类型转化有些情况下可能会出问题:比如数据精度丢失
  2. 显式类型转换将所有情况混合在一起,代码不够清晰

所以C++为了加强类型转换的可视性,引入了四种命名的强制类型转换操作符。下面来一一介绍一下。

四种指针的写法均为 xxx_cast< T >(i),必须加括号,有点像强制类型转换

一、static_cast

static_cast用于非多态类型的转换(静态转换),编译器隐式执行的任何类型转换都可用static_cast,但它不能用于两个不相关的类型进行转换
就是说白了,你不加static_cast可以转换的或者显示类型转换的基本上加了这个也可以。类型不相关的不可以转换。
基本用法

double i = 5;
int j = static_cast<int>(i);

花里胡哨的用法:

class A {
public:explicit A(int x) {}
};
int main()
{A a(5);A a1 = static_cast<A>(5);A a2 = 5;//errorreturn 0;
}

加上explicit不允许实现隐式类型转化,但是可以玩static_cast

class Base
{};
class Derived : public Base 
{
public:int _a;
};int main()
{Base* base = new Derived();Derived* derived2 = static_cast<Derived*>(base); // 可行cout << derived2->_a << endl;return 0;
}

这样可以把父类的指针给子类,但是会有潜在的问题,子类成员无法初始化,所以这样别用,用后面的dynamic_cast

二、reinterpret_cast

有点与static_cast相反,reinterpret_cast操作符通常为操作数的位模式提供较低层次的重新解释,用于将一种类型转换为另一种不同的类型
在这里插入图片描述

int main()
{int d = 4;int* p = reinterpret_cast<int*>(d);int* pd = &d;int address = reinterpret_cast<int>(pd);return 0;
}

三、const_cast

先来看一段代码:

int main()
{const int a = 10;int* p = (int*)& a;(*p)++;cout << a << endl;cout << *p << endl;return 0;
}

在这里插入图片描述
这样是不是很奇怪啊,实际上因为a是const属性,编译器知道他是const,在输出*a的时候会直接取出来这个10,所以这里先介绍一个关键字 volatile,这个意思就告诉编译器他是不稳定的

在这里插入图片描述
加上volatile这句话:
在这里插入图片描述
但是即使加上你想直接赋值也是不可以的

volatile const int a = 10;
a = 5;//error

进而引出了const_cast的作用:
const_cast最常用的用途就是删除变量的const属性,方便赋值

int main()
{const int a = 5;int* p = const_cast<int*>(&a);*p = 4;cout << a << endl;return 0;
}

但是这样还没变。。。。所以还需要加上volatile,所以const_cast只是去掉他的属性,但是需要修改还要进一步操作(最好就别修改)
那他的作用就没有了?当然不是:
在调用一些遗留的非const接口时,若你手上只有const对象,就可以使用const_cast。示例如下:

void func(int* ptr) {// 一些非const操作*ptr += 5;
}int main() {int p = 10;const int* constPtr = &p;// func(constPtr); // errorfunc(const_cast<int*>(constPtr)); // 可行return 0;
}

实现代码的复用:
在一个类中,const和非const版本的成员函数可能有大量重复的代码。这时可以让其中一个函数调用另一个,从而减少代码冗余。
所以,const_cast主要用于在特定场景下移除对象的const或volatile属性,但在使用时必须谨慎,要确保不会对真正的常量对象进行修改,以避免引发未定义行为,

四、dynamic_cast

学过DP的应该知道dynamic是啥,dynamic意思是动态,主要用于具有继承关系的父类和子类之间的转化。
dynamic_cast用于将一个父类对象的指针/引用转换为子类对象的指针或引用
向上转型:子类对象指针/引用->父类指针/引用(不需要转换,赋值兼容规则)(切片)
向下转型:父类对象指针/引用->子类指针/引用(用dynamic_cast转型是安全的)
注意:

  1. dynamic_cast只能用于父类含有虚函数的类(如果不含虚函数就会报错)
  2. dynamic_cast会先检查是否能转换成功,能成功则转换,不能则返回0,与指针不同,引用不能为 nullptr,因此转换失败时会抛出异常。
class A
{
public :
virtual void f(){}
};
class B : public A
{};
void fun (A* pa)
{
B* pb1 = static_cast<B*>(pa);
B* pb2 = dynamic_cast<B*>(pa);
cout<<"pb1:" <<pb1<< endl;
cout<<"pb2:" <<pb2<< endl;
}
int main ()
{A a;B b;fun(&a);fun(&b);return 0;
}

五、RTTI(Run-Time Type Identification)

RTTI 的基本概念
运行时类型识别:允许程序在运行时查询和识别对象的实际类型,而不仅仅依赖于编译时的类型信息。
作用:主要用于解决面向对象编程中的多态性问题,特别是在需要将基类指针或引用转换为派生类类型时。
C++主要通过typeid和dynamic_cast实现。
typeid:返回一个表示对象类型的type_info对象,可以用于比较类型。
dynamic_cast:用于安全地将基类指针或引用转换为派生类类型,失败时返回nullptr(指针)或抛出异常(引用)。
decltype:用来识别类型

总结

虽然这里讲了几种方法,但是实际应用中需要小心的使用转换,建议不要使用,或者在保证安全的情况下使用

相关文章:

  • 『React』组件副作用,useEffect讲解
  • 12:点云处理—调平,角度,平面度,高度,体积
  • Oracle双平面适用场景讨论会议
  • 【MATLAB代码】制导——三点法,二维平面下的例程|运动目标制导,附完整源代码
  • 【Typst】6.布局函数
  • .Net Framework 4/C# 初识 C#
  • 由docker引入架构简单展开说说技术栈学习之路
  • 基于 NXP + FPGA+Debian 高可靠性工业控制器解决方案
  • Dify知识库下载小程序
  • Jpom:Java开发者的一站式自动化运维平台详解
  • RabbitMQ在SpringBoot中的应用
  • RNN结构扩展与改进:从简单循环网络到时间间隔网络的技术演进
  • 网络安全运维实训室建设方案
  • Matlab数值计算
  • YOLO学习笔记 | 一种用于海面目标检测的多尺度YOLO算法
  • 用HTML5 Canvas打造交互式心形粒子动画:从基础到优化实战
  • 悟饭游戏厅iOS版疑似流出:未测试版
  • Pycharm的使用技巧总结
  • Python实例题:Flask实现简单聊天室
  • 【Linux】Linux 进程基础
  • 企业网站规划书范文/站长工具亚洲高清
  • 新网站如何做百度百科/黄页88网官网
  • 工信部资质查询网站/网络推广公司哪家好
  • 宝鸡网站公司排名/网站推广 方法
  • 用织梦做的网站下载/seo关键词排名优化评价
  • 泉山徐州网站开发/国外网络推广