C++四种强制类型转换:

数据类型的本质:

由数据类型(Data Type)来完成确定数据的解释方式。例如int a;表明,a 这份数据是整数,不能理解为手机、电脑、电视等。
数据类型转换的本质就是对数据所占用的二进制位做出重新解释。

1、自动类型转换(隐式):编译器可以根据已知的转换规则来决定是否需要修改数据的二进制位
2、强制类型转换(显式):由于没有对应的转换规则,所以能做的事情仅仅是重新解释数据的二进制位,但无法对数据的二进制位做出修正。

在C++语言中static_cast、const_cast、reinterpret_cast和dynamic_cast四个关键字用于强制类型转换。

四个类型转换操作符

1、static_cast
用于良性转换,一般不会导致意外发生,风险很低。

#include 
#include 
using namespace std;
int main(){
    //正确的用法
    int m = 100;
    long tmp1 = static_cast<long>(m);        //宽转换,没有信息丢失
    char tmp2 = static_cast<char>(m);        //窄转换,可能会丢失信息
    int *p1 = static_cast<int*>(malloc(10)); //将void指针转换为具体类型指针
    void *p2 = static_cast<void*>(p1);       //将具体类型指针,转换为void指针
   
    //错误的用法
    float *p3 = static_cast<float*>(p1);     //不能在两个具体类型的指针之间进行转换
    p3 = static_cast<float*>(0X2DF9);        //不能将整数转换为指针类型

    return 0;
}

2、const_cast
用于 const 与非 const、volatile 与非 volatile 之间的转换。它是唯一一个且仅用于属性的转换的运算符,可去除 const 属性、去除volatile 属性的转换。

将 const 引用转换为同类型的非 const 引用,将 const 指针转换为同类型的非 const 指针时可以使用 const_cast 运算符

const string temp = "Inception";
string& p1 = const_cast <string&> (temp );
string* p2 = const_cast <string*> (&temp );

3、reinterpret_cast
高度危险的转换,这种转换仅仅是对二进制位的重新解释,不会借助已有的转换规则对数据进行调整,但是可以实现最灵活的 C++ 类型转换。

用于进行各种不同类型的指针之间、不同类型的引用之间以及指针和能容纳指针的整数类型之间的转换。转换时,执行的是逐个比特复制的操作。
示例1:

int *pi;  
char *pc = reinterpret_cast<char*>(pi);  

在这里你可以看到reinterpret_cast的强大作用,但是要注意的是,他并没有进行二进制的转换,pc指向的真实对象其实还是int的,不是char

一般用于一下几种场景:

  1. 指针转向足够大的整数类型
  2. 从整形或者enum枚举类型转换为指针
  3. 从指向函数的指针转向另一个不同类型的指向函数的指针
  4. 从一个指向对象的指针转向另一个不同类型的指向对象的指针
  5. 从一个指向成员的指针转向另一个指向类成员的指针!或者是类型,如果类型的成员和函数都是函数类型或者对象类型

4、dynamic_cast
作为四个内部类型转换操作符之一的dynamic_cast和传统的C风格的强制类型转换有着巨大的差别。除了dynamic_cast以外的转换,其行为的都是在编译期就得以确定的,转换是否成功,并不依赖被转换的对象。而dynamic_cast则不然。

首先,dynamic_cast依赖于RTTI信息,其次,在转换时,dynamic_cast会检查转换的source对象是否真的可以转换成target类型,这种检查不是语法上的,而是真实情况的检查。

先看RTTI相关部分,通常,许多编译器都是通过vtable找到对象的RTTI信息的,这也就意味着,如果基类没有虚方法,也就无法判断一个基类指针变量所指对象的真实类型, 这时候,dynamic_cast只能用来做安全的转换,例如从派生类指针转换成基类指针.而这种转换其实并不需要dynamic_cast参与.
也就是说,dynamic_cast是根据RTTI记载的信息来判断类型转换是否合法的。

struct B1{
    virtual ~B1(){}
};
struct B2{
    virtual ~B2(){}
};
struct D1 : B1, B2{};
int main()
{
    D1 d;
    B1* pb1 = &d;
    B2* pb2 = dynamic_cast<B2*>(pb1);	//正确的用法1
    B2* pb22 = static_cast<B2*>(pb1);   //错误的用法2
    return 0;
}

上述定义中可以看到,B1和B2是不相关的类,dynamic_cast允许这种转换:只要B1存在多态方法.
错误用法2将编译失败,static_cast并不允许两个完全不相干的类互相转换.

你可能感兴趣的:(笔记,c++,开发语言)