const_cast
和reinterpret_cast
都是编译时类型转换,简单的说这两种类型转换是告诉编译器,应该将某个变量看作是什么类型,而不会对变量做任何内存上的变动。
在下面的情境下我们讨论这个问题,老王有一个儿子小明和一个女儿小红,老王写了个遗嘱准备留下有遗产10块钱。
小明自己有11块,所以小明总共16块钱;小红自己有12块钱,所以小红总共有17块钱。
我们将这三个人用下面三个类表示:
#pragma once #include<iostream> //父亲:老王 class LaoWang { public: LaoWang() :m_LaoWangMoney(10) {} ~LaoWang() {} virtual void money() { std::cout << m_LaoWangMoney<< std::endl; } int m_LaoWangMoney; }; //老王儿子:小明 class XiaoMing:public LaoWang { public: XiaoMing() :m_XiaoMingMoney(11) {} ~XiaoMing() {} void money() override { std::cout << m_LaoWangMoney / 2 + m_XiaoMingMoney << std::endl; } private: int m_XiaoMingMoney; }; //老王女儿:小红 class XiaoHong:public LaoWang { public: XiaoHong() :m_XiaoHongMoney(12) {} ~XiaoHong() {} void money() override { std::cout << m_LaoWangMoney / 2 + m_XiaoHongMoney << std::endl; } private: int m_XiaoHongMoney; };
const_cast
的作用和条件如下:
const
或者volatile
属性。老王接到一个诈骗电话,但是他开始是坚定的const变量,谁的话都不听。后来骗子用变声器(const_cast
),变成他老婆的声音,去掉了老王的const
,这样老王就被骗走了五块钱。
通过const_cast我们可以临时去除指针或者引用的const
或者volatile
属性,这种方法其实非常不安全,如果这样使用了,一定要能保证程序运行的安全性。
reinterpret翻译过来就是重新解释,这个的含义就是我们可以重新声明这个变量的类型。
我们可以通过reinterpret_cast
将一个变量任意转换,你只需要告诉编译器你要将某个变量看作是什么类型,编译器就会乖乖听话,并执行,不会出现类型转换失败的错误。但是,编译器不会保证后续执行是正确的。
老王、小明、小红和假老王进行角色扮演游戏,他们会声明自己的身份,每个人说自己是谁,我们就必须帮他们当作是谁。但是我们可以通过money( )
这个函数判断他们的真实身份。
首先,我们创建了老王、小明、小红、以及假老王(fake_lao_wang
)三个变量。我们通过reinterpret_cast
对这些变量胡乱转换。编译器也会通过这些语句不会报错。
#include<iostream> #include"class_use.h" #include<memory> using LaoWang_Ptr = std::shared_ptr<LaoWang>; using XiaoMing_Ptr = std::shared_ptr<XiaoMing>; using XiaoHong_Ptr = std::shared_ptr<XiaoHong>; int main() { LaoWang* lao_wang = new LaoWang(); XiaoMing* xiao_ming = new XiaoMing(); XiaoHong* xiao_hong = new XiaoHong(); int fake_lao_wang = 0; XiaoMing* xiao_ming_2 = reinterpret_cast<XiaoMing*>(lao_wang); LaoWang* lao_wang_2 = reinterpret_cast<LaoWang*>(xiao_ming); LaoWang* lao_wang_3 = reinterpret_cast<LaoWang*>(xiao_hong); LaoWang* lao_wang_4 = reinterpret_cast<LaoWang*>(fake_lao_wang); //TODO Something delete lao_wang, xiao_hong, xiao_hong; std::cin.get(); return 0; }
我们在TODO Something位置,调用money( )
函数:
{ xiao_ming_2->money(); lao_wang_2->money(); lao_wang_3->money(); lao_wang_4->money(); }
结果如下:
所以通过reninterpret_cast你可以随意的转换变量,但是你要保证正确的使用。
在文章中,我已经强调很多次了,需要保证程序的安全性,因为这两种转换会打破原有对变量的设计,会带了更大的风险。在这里正确使用,就是尽量不要使用这两种转换。
我们设计程序就三件事情:安全,安全,还塔玛是安全!
点赞收藏加关注,乱杀Bug挡不住!