C++ 四种强制转换cast

C++ 四种强制转换类型函数
2.1 const_cast

1、常量指针被转化成非常量的指针,并且仍然指向原来的对象;
2、常量引用被转换成非常量的引用,并且仍然指向原来的对象;
3、const_cast一般用于修改指针。如const char *p形式。

#include<iostream>
int main() {
    // 原始数组
    int ary[4] = { 1,2,3,4 };

    // 打印数据
    for (int i = 0; i < 4; i++)
        std::cout << ary[i] << "\t";
    std::cout << std::endl;

    // 常量化数组指针
    const int*c_ptr = ary;
    //c_ptr[1] = 233;   //error

    // 通过const_cast<Ty> 去常量
    int *ptr = const_cast<int*>(c_ptr);

    // 修改数据
    for (int i = 0; i < 4; i++)
        ptr[i] += 1;    //pass

    // 打印修改后的数据
    for (int i = 0; i < 4; i++)
        std::cout << ary[i] << "\t";
    std::cout << std::endl;

    return 0;
}

/*  out print
    1   2   3   4
    2   3   4   5
*/

2.2 static_cast

static_cast 作用和C语言风格强制转换的效果基本一样,由于没有运行时类型检查来保证转换的安全性,所以这类型的强制转换和C语言风格的强制转换都有安全隐患。
用于类层次结构中基类(父类)和派生类(子类)之间指针或引用的转换。注意:进行上行转换(把派生类的指针或引用转换成基类表示)是安全的;进行下行转换(把基类指针或引用转换成派生类表示)时,由于没有动态类型检查,所以是不安全的。
用于基本数据类型之间的转换,如把int转换成char,把int转换成enum。这种转换的安全性需要开发者来维护。
static_cast不能转换掉原有类型的const、volatile、或者 __unaligned属性。(前两种可以使用const_cast 来去除)
在c++ primer 中说道:c++ 的任何的隐式转换都是使用 static_cast 来实现。

2.3 dynamic_cast

dynamic_cast强制转换,应该是这四种中最特殊的一个,因为他涉及到面向对象的多态性和程序运行时的状态,也与编译器的属性设置有关.所以不能完全使用C语言的强制转换替代,它也是最常有用的,最不可缺少的一种强制转换.对于从子类到基类的指针转换 ,dynamic_cast 成功转换,没有什么运行异常,且达到预期结果
而从基类到子类的转换 , dynamic_cast 在转换时也没有报错,但是输出给 base2sub 是一个 nullptr ,说明dynami_cast 在程序运行时对类型转换对“运行期类型信息”(Runtime type information,RTTI)进行了检查.
这个检查主要来自虚函数(virtual function) 在C++的面对对象思想中,虚函数起到了很关键的作用,当一个类中拥有至少一个虚函数,那么编译器就会构建出一个虚函数表(virtual method table)来指示这些函数的地址,假如继承该类的子类定义并实现了一个同名并具有同样函数签名(function siguature)的方法重写了基类中的方法,那么虚函数表会将该函数指向新的地址。此时多态性就体现出来了:当我们将基类的指针或引用指向子类的对象的时候,调用方法时,就会顺着虚函数表找到对应子类的方法而非基类的方法。因此注意下代码中 Base 和 Sub 都有声明定义的一个虚函数 ” i_am_virtual_foo” ,我这份代码的 Base 和 Sub 使用 dynami_cast 转换时检查的运行期类型信息,可以说就是这个虚函数
2.4 reinterpret_cast

reinterpret_cast是强制类型转换符用来处理无关类型转换的,通常为操作数的位模式提供较低层次的重新解释!但是他仅仅是重新解释了给出的对象的比特模型,并没有进行二进制的转换!
他是用在任意的指针之间的转换,引用之间的转换,指针和足够大的int型之间的转换,整数到指针的转换
“reinterpret_cast 运算符并不会改变括号中运算对象的值,而是对该对象从位模式上进行重新解释”一个指向字符串的指针是如何地与一个指向整数的指针或一个指向其他自定义类型对象的指针有所不同呢?从内存需求的观点来说,没有什么不同!它们三个都需要足够的内存(并且是相同大小的内存)来放置一个机器地址。指向不同类型之各指针间的差异,既不在其指针表示法不同,也不在其内容(代表一个地址)不同,而是在其所寻址出来的对象类型不同。也就是说,指针类型会教导编译器如何解释某个特定地址中的内存内容及其大小。”参考这段话和下面的内存示意图,答案已经呼之欲出了。

使用reinterpret_cast运算符把pnum从int转变成char类型并用于初始化pstr后,pstr也指向num的内存区域,但是由于pstr是char类型的,通过pstr读写num内存区域将不再按照整型变量的规则,而是按照char型变量规则。一个char型变量占用一个Byte,对pstr解引用得到的将是一个字符,也就是’a’。而在使用输出流输出pstr时,将输出pstr指向的内存区域的字符,那pstr指向的是一个的字符,那为什么输出三个字符呢?这是由于在输出char指针时,输出流会把它当做输出一个字符串来处理,直至遇到’\0’才表示字符串结束。对代码稍做改动,就会得到不一样的输出结果,例如将num的值改为0x63006261,输出的字符串就变为”ab”。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

无敌秋

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值