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

c++11: 类型转换

目录

一 C语言中的类型转换

二 . C++强制类型转换 

1. static_cast

2. reinterpret_cast

3. const_cast

4. dynamic_cast

三 explicit 关键字 


 

一 C语言中的类型转换

在C语言中,如果赋值运算符左右两侧类型不同,或者形参与实参类型不匹配,或者返回值类型与接收返回值 类型不一致时,就需要发生类型转化,C语言中总共有两种形式的类型转换:隐式类型转换和显式类型转换

  • 隐式类型转化:编译器在编译阶段自动对相近类型进行转换
int main()
{int i = 1;double d = 6.66;i = d;//在这里编译器进行了隐式类型转换(前提相近类型)//将double转成int类型cout << i << endl;return 0;
}

运行结果会有一定的精度损失

  • . 显式类型转化:需要用户自己处理 (处理不相近类型)
    int* p = nullptr;p = (int*)i;//不相近类型,需要我们手动进行强制转换类型cout << p << endl;

缺陷: 转换的可视性比较差,所有的转换形式都是以一种相同形式书写,难以跟踪错误的转换。 


二 . C++强制类型转换 

 c++兼容c语言留下来的隐式类型转换和显示类型转换,但是c++觉得c语言做的不规范,且可视性比较差,为了加强类型转换的可视性,引入了四种命名的类型转换操作符。

static_cast、      reinterpret_cast、    const_cast、     dynamic_cast

1. static_cast

//对应c语言的隐式类型转换(相近类型)d=static_cast<double>(i);

2. reinterpret_cast

//对应c语言的强制类型转换(不相近类型)p = reinterpret_cast<int*>(i);

static_cast<>() 类似个类的使用,所以在使用上我们传模板<double>已经传参数(i)   

3. const_cast

    const int ci = 10;int* pi = const_cast<int*>(&ci);//去掉const属性//对应c语言的强制类型转换  int* pi = (int*)&ci;

接下来我们看一个测试题

int main()
{const int ci = 10;int* pi = const_cast<int*>(&ci);//去掉const属性//对应c语言的强制类型转换  int* pi = (int*)&ci;*pi = 20;cout << *pi << endl;cout << ci << endl;//return 0;}

测试结果

按理说所得结果ci应该为ci=20的,但是这里为啥还是10? 关于这种问题,在linux相关文章中也介绍过了,在main()中, 由于const int ci=10, 编译器会认为 const ci不会改变的,所以cpu会把ci存储在cpu里的寄存器中,不再每次向内存中读取ci的值了,所以后面尽管*pi=20即将ci对应的内存值改成20,但因为cpu并没有去读取,所以输出结果依然ci=10. 

 🍎在之前的文章中也介绍过,要想让寄存器到内存中读取const int ci 的值,我们需要在其前面加一个关键词  volatile (即内存可见)

    volatile const int ci = 10;int* pi = const_cast<int*>(&ci);//去掉const属性//对应c语言的强制类型转换  int* pi = (int*)&ci;*pi = 20;cout << *pi << endl;cout << ci << endl;//

测试结果:这样就符号我们的预期了

4. dynamic_cast

dynamic_cast     用于将一个父类对象的指针/引用转换为子类对象的指针或引用(动态转换)

  •     c++中子类对象可以赋值给父亲的对象指针引用,这个过程会发生切片,天然支持
A a;B b;A* pa = &a;pa = &b;
  • 如果父类的指针或引用传给子类的指针,这个过程有可能成功
class A
{
public://虚函数virtual void f(){}int _a;
};
class B :public A
{
public://虚函数virtual void f(){}int _b;
};//A a;
//B b;
//A* pa = &a;
//f_cast(pa);
//pa = &b;
//f_cast(pa);
void f_cast(A* pa)
{//如何区分pa是指向父类还是子类B* pb = (B*)pa;pb->_a = 1;pb->_b = 2;cout << pb->_a << endl;cout << pb->_b << endl;}
int main()
{A a;B b;A* pa = &a;//pa = &b;f_cast(pa);return 0;
}

这个测试例子主要是用于:pa是父类对象A的指针,当我们传过去给f_cast(pa),函数内部会将pa转成B* 类型的,那我们传入了父类指针能调用 pb->_a = 1; pb->_b = 2;吗?答案是不行的

若我们  pa = &b;   f_cast(pa);即将子类对象指针传入会怎么样呢?

所以c语言中的 void f_cast(A* pa)   B* pb = (B*)pa;pb->_a = 1;  pb->_b = 2;  并不能帮我们区分pa是指向父类还是子类。而c++中的dynamic_cast<B*>(pa) 就能很好解决这个问题。

void f_cast(A* pa)
{//如何区分pa是指向父类还是子类//如果pa指向子类对象,则转换成功//如果pa指向父类对象转换失败返回nullptrB* pb = dynamic_cast<B*>(pa);if (pb != nullptr){cout << "指向子类对象" << endl;pb->_a = 1;pb->_b = 2;}else{cout << "转换失败" << endl;}
}

注意:dynamic_cast只能用于含有虚函数的类 (父类需要有虚函数)这是为什么呢?

因为dynamic_cast通过 ---->去虚表上方的存储标识信息来知道到底是那个类。

还有一个混淆点,虚继承对应有虚基表,虚函数的多态对应虚表。


三 explicit 关键字 

我们先看一个例子:

 class A{public ://构造函数A (int a){cout<<"A(int a)" <<endl;}//拷贝构造A(const A& a){cout<<"A(const A& a)" <<endl;}private :int _a ;};int main (){A a1 (1);// 隐式转换-> A tmp(1); A a2(tmp);//即先构造tmp(1) 然后再拷贝A a2(tmp)A a2 = 1;}

这也是我们之前在写模拟STL的时候为什么构造函数和拷贝构造创建好之后也可以不用重载=

因为A  a2=1;编译器会进行 隐式转换。

为了阻止这种行为我们可以用explicit 关键字。explicit关键字阻止经过转换构造函数进行的隐式转换的发生

  explicit A (int a){cout<<"A(int a)" <<endl;}

当不进行=赋值重载再运行代码的时候会报错。

 

 

http://www.xdnf.cn/news/2698.html

相关文章:

  • dummy cli-tool ubuntu22.04使用
  • 在 Git 中,撤销(回退)merge 操作有多种方法
  • terraform 动态块(Dynamic Blocks)详解与实践
  • [Python开发] 如何用 VSCode 编写和管理 Python 项目(从 PyCharm 转向)
  • Java面试:Spring及Spring Cloud技术深度剖析
  • docker安装部署TDengine实现主从复制
  • 雷池WAF的身份认证 - GitHub
  • <uniapp><插件><UTS>在uniapp中,创建自己的插件并发布到uni插件市场
  • JavaScript-基础语法
  • 「Mac畅玩AIGC与多模态05」部署篇03 - 在 Mac 上部署本地向量化模型(Embedding Models)
  • 在QGraphicsView中精确地以鼠标为锚缩放图片
  • 迈瑞医疗一季度业绩环比大幅改善 国内业务将从今年三季度迎来重大拐点
  • 用Java模拟打字:深入解析 java.awt.Robot 的键盘控制艺术
  • 【Robocorp实战指南】Python驱动的开源RPA框架
  • 【Vue3-Bug】中路由加载页面直接显示空白
  • 【面经分享】长鑫存储Java研发一面|40分钟速战速决
  • python_股票月数据趋势判断
  • HTML标记语言_@拉钩教育
  • leetcode0230. 二叉搜索树中第 K 小的元素-medium
  • C++?模板!!!
  • ai环境cuda cudnn conda torch整体迁移 wsl docker
  • 在使用Python的Selenium库打卡网页后,通过CDP命令获取所有cookies(包括Httponly和Secure的cookies)
  • 如何使用electron-forge开发上位机ui
  • 如何开展有组织的AI素养教育?
  • zynq 7010 PS 串口打印
  • 绘制板块层级图
  • 健康养生:开启品质生活的密钥
  • 【jceks】使用keytool和hadoop credential生成和解析jceks文件(无密码storepass)
  • 零基础搭建AI作曲工具:基于Magenta/TensorFlow的交互式音乐生成系统
  • 【计算机视觉】Bayer Pattern与Demosaic算法详解:从传感器原始数据到彩色图像