C++显式转换(3)-const

    xiaoxiao2021-03-25  132

    如果光看名字,没准会觉得const_cast是给变量增加const特性。其实正相反,这个转换的功能是去掉变量的const特性的。

    还是先看代码:

    Person类有除了构造函数以外有2个方法,getHeight和growUp。其中getHeight方法声明的最后有一个const关键字,它的含义是对外保证getHeight方法不会改变数据成员的内容。我们姑且把它称为const-1:const方法。另外一个函数growUp需要修改m_height的值,当然也就不能有这种承诺。

    这部分代码是一个架空的函数。内容主要是调用了persongetHeight和growUp方法。

    在第20行,test函数的参数声名的第一个词也是const关键字。这个const是向本函数的调用者保证:”把person交给我吧,我是不会修改参数persion的内容的“。另一方面,不管实际调用时person是否具有const特性,在函数的内部都是当作const数据来使用的。也就是它指向的对象的内容不能被修改。我们把这种情况成为const-2:const形参。

    getHeight被调用时,因为getHeight已经保证不会修改person的内容,可以满足person不被修改的需求,所以不会出现任何问题。

    如果我们同样调用growUp方法的话,就会产生编译错误。想想也是,growUp没有保证不修改person的内容,违反了test函数对外做过的保证。

    这是C++const体系应该有的样子,一切都基于协议,运作地非常好。

    但是如果非要改怎么办呢?

    就像25行那样,可以利用const_cast去掉person的const特性,然后就可以像一切都没有发生似的,调用growUp方法了。

    如果你忽然有一种不靠谱的感觉,那么祝贺你,你是个很不错的C/C++程序员!

    接下来,结合下面的例子来看看,到底什么时候靠谱,什么时候不靠谱。

    程 序的30行定义了一个非const的normal_person,然后调用了test函数。虽然在test内部我们调用了growUp函数改变 normal_person的内容,但是并不会引起任何不适,因为normal_person本来就可以被改变的,只是test自己说不改的。

    和30行不同,33行我们定义一个const的stone_person。这种情况我们成为const-3:const变量。我们的本意是石头人不可能长高。但是调用过test之后,石头人也会长高。

    这有什么问题么?我这是很大的问题,因为程序世界的规则被打破了。在有些系统中,stone_person很可能被定义在只读空间内,这是一个写操作让系统挂掉也不一定。

    实际的开发中还有另外一种情况(可能更多),就是有些方法从实际的实现上来看并不会修改对象的内容,只是没有被定义为const方法。这是也不会产生本质的问题。

    不管哪一种情况,test函数都违反了当初的承诺,放弃了本来可以由编译器可以进行的检查,程序员自己要认真评估const_cast造成的影响并谨慎使用才行。

    是不是很负面?

    那要看和谁比,和C语言的强制类型转换比起来的话,还是要强很多的。至少向编译器,向程序的读者表明了要做什么,使之有可能进行进一步的检查。

    这一点必须搞清楚。


    阅读最新文章请扫描下面二维码,关注公众号【面向对象思考】。

    转载请注明原文地址: https://ju.6miu.com/read-5810.html

    最新回复(0)