c++强制类型转换

一、static_cast:
作用:static_cast < type-id > ( expression ),该运算符把expression转换为type-id类型,但没有运行时类型检查来保证转换的安全性(编译时类型检查),它主要有如下几种用法:
(1)用于基本数据类型之间的转换,如把int转换为char,把int转换成enum,但这种转换的安全性需要开发者自己保证(这可以理解为保证数据的精度,即程序员能不能保证自己想要的程序安全),如在把int转换为char时,如果char没有足够的比特位来存放int的值(int>127或int<-127时),那么static_cast所做的只是简单的截断,及简单地把int的低8位复制到char的8位中,并直接抛弃高位。
比如下面的例子:int转换为short时,直接把低十六位寄存器ax中的位拷贝到c。
这里写图片描述
(2)把空指针转换成目标类型的空指针
(3)把任何类型的表达式类型转换成void类型
(4)用于类层次结构中父类和子类之间指针和引用的转换。
对于以上第(4)点,存在两种形式的转换,即上行转换(子类到父类)和下行转换(父类到子类)。对于static_cast,上行转换时安全的,而下行转换时不安全的,为什么呢?因为static_cast的转换时粗暴的,它仅根据类型转换语句中提供的信息(尖括号中的类型)来进行转换,这种转换方式对于上行转换,由于子类总是包含父类的所有数据成员和函数成员,因此从子类转换到父类的指针对象可以没有任何顾虑的访问其(指父类)的成员。而对于下行转换为什么不安全,是因为static_cast只是在编译时进行类型坚持,没有运行时的类型检查。

二、const_cast:
作用:用来强制移除变量的CV属性(这里我们只讨论const属性)。

    int i = 1; //改为const int i;
    cout << "i turns out to be: " << i << endl;
    const int* pc = &i;
    int* modifier = const_cast<int*>(pc);
    *modifier = 2;
    cout << "i now is: " << i << endl;
    cout << "*modifier is :  " << *modifier << endl;

结果:这里写图片描述

如果上例第一句是const int i = 1; 那么再按照这种方式去修改i的值将会产生未定义行为!

其实,const_cast最主要是应用在函数重载中。《Effective C++》中有个很好的例子:

class TextBlock
{
  public:
    //...
    const char& operator[](size_t position) const//常成员函数
    {
      //...
      return text[position];
    }

    char& operator[](size_t position)
    {
      //...
      return    //这里现给调用者加上const属性,
        const_cast<char&>(  //成为一个const TextBlock对象
          static_cast<const TextBlock>(*this) //再调用const operator[]
            [position]); //最后移除返回值的const属性,实现安全的代码复用
     }
     //...
  private:
    string text;
    //...
};    

三、reinterpret_cast:
作用:用来处理无关类型之间的转换;它会产生一个新的值,这个值会有与原始参数(expressoin)有完全相同的比特位(比特位的重新解释)。

滥用 reinterpret_cast 运算符可能很容易带来风险。 除非所需转换本身是低级别的,否则应使用其他强制转换运算符之一。

reinterpret_cast 运算符可用于 char* 到 int* 或 One_class* 到 Unrelated_class* 之类的转换,这本身并不安全。

reinterpret_cast 的结果不能安全地用于除强制转换回其原始类型以外的任何用途。 在最好的情况下,其他用途也是不可移植的。

reinterpret_cast 运算符不能丢掉 const、volatile 或 __unaligned 特性。

reinterpret_cast 运算符将 null 指针值转换为目标类型的 null 指针值。

reinterpret_cast 的一个实际用途是在哈希函数中,即,通过让两个不同的值几乎不以相同的索引结尾的方式将值映射到索引。

#include <iostream>  
using namespace std;  

// Returns a hash code based on an address  
unsigned short Hash( void *p ) {  
   unsigned int val = reinterpret_cast<unsigned int>( p );  
   return ( unsigned short )( val ^ (val >> 16));  
}  

using namespace std;  
int main() {  
   int a[20];  
   for ( int i = 0; i < 20; i++ )  
      cout << Hash( a + i ) << endl;  
}  

四、dynamic_cast:
使用形式如下:

dynamic_cast<type*>(e); //e是有效指针
dynamic_cast<type&>(e); //e是左值
dynamic_cast<type&&>(e);//e是右值

type是类类型且通常含有虚函数。e的类型是以下3中情况之一:

  • type的公有子类
  • type的公有父类
  • 与type同类型

即能进行的转换是:

  • 1.子类向基类的向上转型(Up Cast)
  • 2.基类向子类的向下转型(Down Cast)
  • 3.横向转型(Cross Cast)

向上转型是多态的基础,需不要借助任何特殊的方法,只需用将子类的指针或引用赋给基类的指针或引用即可,当然dynamic_cast(static_cast)也支持向上转型,而其总是肯定成功的。
对于指针的“向下转型”有两种情况。一种是基类指针所指对象是派生类类型的,这种转换是安全的;另一种是基类指针所指对象为基类类型,在这种情况下dynamic_cast在运行时做检查,转换失败,返回结果为0;

class Base
{
public:
    Base(){};
    virtual void Show(){cout<<"This is Base calss";}
};

class Derived:public Base
{
public:
    Derived(){};
    void Show(){cout<<"This is Derived class";}
};

    //这是第一种情况
    Base* base = new Derived;
    if(Derived *der= dynamic_cast<Derived*>(base))
    {
        cout<<"第一种情况转换成功"<<endl;
        der->Show();
        cout<<endl;
    }

    //这是第二种情况
    Base * base1 = new Base;
    if(Derived *der1 = dynamic_cast<Derived*>(base1))
    {
        cout<<"第二种情况转换成功"<<endl;
        der1->Show();
    }
    else 
    {
        cout<<"第二种情况转换失败"<<endl;
    }

也可以使用dynamic_cast将基类引用转换为派生类引用,同样的,引用的向上转换总是安全的;与指针一样,引用的向下转型也可以分为两种情况,与指针不同的是,并不存在空引用,所以引用的dynamic_cast检测失败时会抛出一个bad_cast异常。
使用dynamic_cast转换的Base类至少带有一个虚函数。
一个例题:

//假如有继承关系:A <- B <- C <- D <- E
A* a = new C; // 本质
B* b = dynamic_cast<B*> (a); // 成功,因为B是C的父类
E* e = dynamic_cast<E*> (a); // 失败,因为E是C的子类,返回空指针
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值