C++中四种强制类型的转换

在C语言中,有隐式类型的转换和强制类型的转换.
隐式类型的转换:相关类型的转换,即意义相似的类型.
强制类型的转换:不类型类型的转换,比如:指针和整型.
例如:

int i = 20;
double d = i;//隐式类型的转换.
int* p = (int*)i;//强制类型的转换.

以下是C++的类型转换的四种类型.它们都是类模板.

static_case(静态转换)

不可以用于多态类型的转换.
不可以用于静态类型的转换.
例如:

    7     int i = 3;
    8     double b1 = static_cast<double>(i);
    9     cout<<b1<<endl;

但是不相关类型是不可以转换的,比如下面:

int* p = static_cast<int*>(i);    //i 是整型,转为int*是不可以的

整形和指针属于两种完全不同的类型,所以是不可以通过static_cast转换.

reinterpret_cast(不相关类型的转换)

reinterpret的英文含义有重新转换的含义.
就相当于C语言中不相关类型的转换,强转.
在上面的例子中,不相关类型使用static_cast是不可以转换的.
例如:

int* p = static_cast<int*>(i);

但是可以通过reinterpret_cast来进行转换.
例如:

int* p = reinterpret_cast<int*>(i);

不仅仅只有变量类型可以转换,函数也可以:

  6 typedef void(*Fun)();    //函数指针
  7 int Test(int i)
  8 {
  9     cout<<"Test"<<endl<<i<<endl;
 10     return 0;
 11 }
 12 void fun()
 13 {
 14     Fun f = reinterpret_cast<Fun>(Test);
 15     f();
 16 }

但是不建议使用reinterpert_cast来进行函数指针的强转,完全可以用C语言的强转来实现.

const_cast

 19     const int i = 10; //const修饰的变量会被编译器优化到寄存器中,再次访问该变量时,就会直接从寄存器中区读取...
 20     int* p = const_cast<int*>(&i);
 21     *p = 20;
 22     cout<<i<<endl;
 23     cout<<*p<<endl;

运行结果:
这里写图片描述
解决:加volatile

 19     volatile const int i = 10; //const修饰的变量会被编译器优化到寄存器中,再次访问该变量时,就会直接从寄存器中区读取...
 20     int* p = const_cast<int*>(&i);
 21     *p = 20;
 22     cout<<i<<endl;
 23     cout<<*p<<endl;

dynmic_cast(动态转换)

目的:用于讲一个父类的指针/引用转化为子类的指针/引用.在前面的学习中,我们知道,把一个子类的指针或引用转化为父类的指针/引用,这是可以很自然的转换,会发生切片的行为.
这种类型的转换在C语言中是不支持的,因为在C语言中还没有出现多态.
这里写图片描述
使用场景:
1.dynamic只能用于含有虚函数的类.
2.dynamic在进行转换时先会检查是否会转换成功,能成功则转,不成功就会返回0;

   36 void fun(AA* ptr)                                                                                                  
   37 {
   38     ptr->F();
   39     BB* b = (BB*)ptr;
   40     cout<<"a:"<<b->a<<endl;
   41     cout<<"b:"<<b->b<<endl; //如果是将父类转换为子类时,由于父类中没有变量b,因此就会是随机值.
   42 }

 59 int main()                                                                                                           
 60 {
 61     AA a;
 62     a.a = 1;
 63     BB b;
 64     b.a = 10;
 65     b.b = 100;
 66     fun(&a);
 67     fun(&b);
 68 }

所以为了解决上面的问题,同时打印父类和子类的成员变量.所以此时就可以使用dynamic_cast来进行转换了.

 43 void fun(AA* ptr)
 44 {                                                                                                                    
 45     ptr->F();
 46     BB* b = dynamic_cast<BB*>(ptr); //先会检查是否转换成功,如果转换失败,就会返回0;
 47     if(b)
 48     {
 49         cout<<"转换成功"<<endl;
 50         cout<<"a:"<<b->a<<endl;
 51         cout<<"b:"<<b->b<<endl; 
 52     }
 53     else
 54     {
 55         cout<<"转换失败"<<endl;
 56         cout<<"a:"<<ptr->a<<endl;
 57     }
 58 }

运行结果为:
这里写图片描述
如果此时在BB类中不重写F()函数.但是父类AA()类有虚函数,有虚表.BB类继承了AA自然也会有虚表,所以在子类中不重写虚函数也可以用来转换.但是如果在父类中没有虚函数,那么就会直接编译不通过.

在C++中,支持单参数的隐式类型的转换.只能有一个成员变量
例如:

   52 class CC
   53 {
   54     public:
   55         CC(int _a)                                                                                          
   56             :a(_a)
   57         {
   58             cout<<"a:"<<a<<endl;
   59         }
   60     private:
   61         int a;
   62 };
   63 int main()
   64 {
   65     CC c(10);      
   66     CC c1 = 20;    //属于隐式类型的转换.. 建议使用:CC c = static_cast<CC>(20);
   67     return 0;
   68 }

运行结果为:
这里写图片描述
但是如果不想发生隐式类型的转换,就可以加上关键字:explicit.
加上关键字后就可以防止被转换,直接会编译报错.
这里写图片描述

猜你喜欢

转载自blog.csdn.net/Yinghuhu333333/article/details/80722389