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

一文详解C++中的类型转化

1. C语言中的类型转换

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

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

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

举个例子:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

intmain()

{

doublei = 4.2;

//隐式类型转化

inta = i;

//显示的强制类型转换

intb = (int)i;

int*p=&a;

intd=(int)p;

cout << i << endl;

cout << b << endl;

cout << a << endl;

cout << d << endl;

}

那为什么还要出现C++中的类型转换呢?

因为C语言中的隐式类型转换会带来很多问题:

比如:

1

2

3

4

5

6

7

8

9

intmain()

{

inti = 0;

size_tsize = 5;

while(size >= i)

{

size--;

}

}

size是无符号整型,i是int,在操作符两端的类型就会发生整型提升,导致size永远大于0,造成死循环。所以C++出了一套类型转化的规范写法。

隐式类型转化有些情况下可能会出问题:比如数据精度丢失

显式类型转换将所有情况混合在一起,代码不够清晰

因此C++提出了自己的类型转化风格,注意因为C++要兼容C语言,所以C++中还可以使用C语言的转化风格。

2. C++强制类型转换

static_cast,reinterpret_cast,const_cast,dynamic_cast,这是c++规范的四种类型转化。

1. static_cast

2.reinterpret_cast

3.const_cast

我们来看一个例子:

1

2

3

4

5

6

7

8

9

intmain()

{

constinta = 2;

int* p =const_cast<int*>(&a);//去掉const属性

*p = 5;

cout << a << endl;

cout << *p << endl;

return0;

}

大家可以猜一下结果是什么?

可能有人会想,这不是改变了吗?为什么还是2呢?

原因是:在编译时,因为是const修饰(不会修改),所以就会把a的值放入寄存器中,通过*p来改变的是内存中的a的值,但是a在寄存器中的值没有改变,依旧是2,所以打印时就是2。为了防止这种优化行为的发生,就会在a的前面加:volatile const int a=2;(表明了a的值会改变,不要放在寄存器中),所以每次去取a的值就会到内存中去取。(保持内存可见性)

就因为const_cast会导致这种危险行为的发生,所以C++就会把const_cast这个类型转化单独拿出来,但用的时候很危险!

可以看出,const_cast取消了const属性。

4.dynamic_cast

这种类型转化是专门来针对父类和子类指针之间的相互转化的:

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

向上转型:子类对象指针/引用->父类指针/引用(不需要转换,赋值兼容规则,天然的一种行为)

向下转型:父类对象指针/引用->子类指针/引用(用dynamic_cast转型是安全的)

注意:

1. dynamic_cast只能用于父类含有虚函数的类

2.dynamic_cast会先检查是否能转换成功,能成功则转换,不能则返回0

如果我们不使用dynamic_cast来进行向下转型(父类转化为子类),那就会发生越界的情况:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

classA

{

public:

virtualvoidf() {}

int_a = 0;

};

classB :publicA

{

public:

int_b = 0;

};

//C语言中的强转

//void Func(A* ptr)

//{

// // 直接转换是不安全的

// B* bptr = (B*)ptr; //父类转子类

// cout << bptr << endl;

//

// bptr->_a++;

// bptr->_b++; //发生越界

//

// cout << bptr->_a << endl;

// cout << bptr->_b << endl;

//}

voidFunc(A* ptr)

{

// C++规范的dynamic_cast是安全的

// 如果ptr是指向父类,则转换失败,返回空

// 如果ptr是指向子类,则转换成功

B* bptr =dynamic_cast<B*>(ptr);

cout << bptr << endl;

if(bptr)

{

bptr->_a++;

bptr->_b++;

cout << bptr->_a << endl;

cout << bptr->_b << endl;

}

}

intmain()

{

A aa;

B bb;

Func(&aa);

Func(&bb);

return0;

}

总结

这就是C++中的四种类型转化,但是强制类型转换关闭或挂起了正常的类型检查,每次使用强制类型转换前,程序员应该仔细考虑是否还有其他不同的方法达到同一目的,如果非强制类型转换不可,则应限制强制转换值的作用域,以减少发生错误的机会。 强烈建议:避免使用强制类型转换

http://www.cnnetsun.cn/news/2970665.html

相关文章:

  • Arnis:如何用创新工具一键生成逼真的Minecraft城市世界?
  • 突破传统:LightX2V如何重新定义视频生成推理
  • Cactbot安全使用指南:如何合规使用FFXIV战斗辅助工具
  • MC68060总线信号深度解析:从硬件通信原理到嵌入式系统设计实践
  • R3nzSkin国服特供版:5分钟解锁英雄联盟全皮肤免费体验指南
  • 3步解锁QQ音乐加密文件:macOS用户必备的格式转换终极指南
  • CANN/GE SubgraphBoundary构造与析构
  • Crawl4AI:智能网页数据提取工具,让AI应用开发更简单
  • Python数据采集+机器学习:7×24小时企业级舆情监控系统完整落地指南
  • 如何用Tiny11Builder打造你的专属轻量级Windows 11系统?3步解决系统臃肿问题
  • Seedance 2.0 国内实战指南:API调用、中转站选型与Iris Out生成
  • 网盘直链下载助手:3分钟告别客户端,实现真正的高速下载自由
  • MC68HC908EY16A FLASH编程与ADC10模块:嵌入式系统稳定性的硬件基石
  • Page Assist终极指南:3分钟让本地AI成为你的网页助手
  • NAS上部署AgentMemory:DeepSeek压缩+Tailscale远程访问实战
  • Grok-4.3 Beta可信路径建模:让大模型推理可验证、可调控
  • GPT-4o高阶提示词设计:锚点、节奏与留白三大范式
  • Grok-3 v3.2.4热更新深度解析:大模型工程化落地的毫米级优化
  • GPT-4o协同建模:重构程序员的思考操作系统
  • 戴尔G15散热控制终极指南:开源AWCC替代方案完全解析
  • 新手关于AI claude code的使用步骤
  • MC9S08GB/GT硬件设计:从ESD防护到直流电气特性的可靠性实战解析
  • 企业级大模型推理七堵墙:显存、通信、IO等硬性瓶颈实战拆解
  • NTFS压缩实战指南:在HDD与SSD上权衡性能与空间的决策
  • ESP32实战-OLED驱动与动态数据显示
  • 嵌入式ADC队列化设计:QADC扫描模式与边界条件深度解析
  • 4-流形中非定向曲面嵌入的法欧拉数约束研究
  • 惠勒-闭弦宇宙信息基元演化方程:基于自指不动点的拓扑信息论(世毫九实验室原创研究)
  • 反智的圣殿:波普尔证伪主义的思想病毒本质与“贾子语言”对真理的复归
  • 3分钟解决微信语音无法播放的终极方案:Silk v3解码器完全指南