C++11中const_cast的真实使用场景

马谦马谦马谦 C/C++1 1,5792字数 1173阅读3分54秒阅读模式

一、const和成员函数的故事

const的用途有以下几种:

  1. 修饰全局、局部、成员变量
  2. 修饰成员函数

修饰变量的时候const限制了变量在整个程序运行期间都是不能修改的,而修饰成员函数的时候限制函数内不能修改数据成员,这应该是所有C++程序员都烂熟于心的准则。但除了这两条准则以外,const还有一些隐含的准则,是写代码的时候是很容易被忽视的。例如以下代码,相信很多人都无法一眼看出这段代码的问题在哪:

其实问题很简单:PrintHeroName函数的形参是一个const类型的Hero对象,但是在函数体内,这个const类型的Hero对象调用了一个非const的成员函数,这是不允许的。这种情况下,编译器会报错:

如果想要在PrintHeroName函数中调用h.GetName方法,只需要把形参里的const去掉就可以了。或者把GetName修改成一个const属性的成员函数。

其实最开始我也没有发现这段代码的问题,作为亲手写下这段代码的始作俑者,我甚至还捉摸了一段时间。但这其实就是一个简单的用法,因为使用得过于习惯,并且自认为非常熟悉,所以就忽视了问题所在。

二、为什么要使用const_cast

const_cast的作用是去掉变量的const或者volatile限定符——这看起来很鸡肋,因为很多人都在想:我既然要去掉const限制,那我直接不使用const修饰不就完事了吗?何必多此一举?其实最开始我也是这么认为的,所以从来没有用过这个关键字。直到今天遇到上面的那个问题之后,才突然明白const_cast的真正用途。

上面的程序,把PrintHeroName形参的const去掉后,程序可以正常编译了。问题是,如果调用它的上层函数,Hero对象已经被const限定了,应该怎么办?例如:

可以看到,CreateHero的形参是const的,但PrintHeroName是非const的,无法在CreateHero函数中将h传递到PrintHeroName,因为不能直接将一个const对象转换成非const的。程序编译也会报错:

这种情况下就要用到const_cast了,这里才是const_cast大展拳脚的地方:因为我们很明确能知道GetName()是不会修改任何成员对象的值的,所以可以在这里通过const_cast去掉Hero的const限定,使得程序可以正常往下调用。即,只要把h通过const_cast包裹起来就可以了:

 最后更新:2020-10-25
马谦马谦马谦
  • 本文由 马谦马谦马谦 发表于 2020年10月19日23:05:33
  • 转载请务必保留本文链接:https://www.dyxmq.cn/program/code/c-cpp/const_cast.html
C++11中的override和final关键字 C/C++

C++11中的override和final关键字

一、前言 昨天在公司做代码扫描,发现很多类似以下的代码都产生了告警,导致扫描不通过: virtual int func() override {} 不通过的原因是:同时使用virtual和overri...
C++文件输入输出流fstream的基本用法 C/C++

C++文件输入输出流fstream的基本用法

一、文件流 C++的IO类中定义了三个文件读写流fstream、ifstream以及ofstream,它们都继承于相同的父类istream,通过不同的实现以实现不同的文件流操作。 三者的区别为: if...
    • zzz
      zzz 0

      修改为
      void PrintHeroName(const Hero &h)
      应该是一个更好的方案

    匿名

    发表评论

    匿名网友
    :?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:
    确定

    拖动滑块以完成验证