c++:浅谈强制类型转换

c语言中我们经常使用到强制类型转换,但为什么c++中还要学习新的强制类型转换呢?当然是为了更加方便和灵活地控制不同类型间的强制转换。

针对不同的应用需要c++制定了一套专用的强制类型转换:static_cast reinterpret_cast const_cast dynamic_cast四种操作符。<

接下来,让我们一一道来!
首先,我们要分清隐式类型转换和显示的强制类型转换。
隐式类型转换

int main()
{
    int i = 1;
    double d = i;//这里i赋值给d过程会生成具有常性临时变量 
    printf("%d,%.2f\n",i,d);
    return 0;
}

这里写图片描述
显式的类型转换

int main()
{
    int i=1;
    int *p =& i;
    int a = (int)p;//将指针类型强制转换为整型
    printf("%x,%d\n",p,a);
    return 0;
}

这里写图片描述

static_cast
-相关类型的转换,类似C语言隐式类型转换

static_cast用于非多态类型的转换(静态转换),任何标准转换都可以它,但它不能用于两个不相关类型进行转换。

什么是相关类型呢?比如 int和char,double是相关类型,int和int*是非相关类型。
举个例子,将int型变量转换为double类型:

#include<iostream>
using namespace std;
int main()
{
    int i = 1;
    double d = static_cast<double>(i);
    printf("%d,%.2f\n",i,d);
}

这里写图片描述
reinterpret_cast

-不相关类型的转换,类似C语言强制类型的转换
把一个指针类型转换成一个整数类型等
eg:

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

其实reinterpret_cast强制转换也是一个比较bug的操作,要小心使用!

#include<iostream>
using namespace std;
typedef void (*FUNC)();
int Something(int i)
{
    cout<<"Something"<<endl;
    return 0;
}
int main()
{
    FUNC f=reinterpret_cast<FUNC>(Something);
    f();
}

这里写图片描述

reinterpret_cast可以使编译器以FUNC的方式去看待Something。上面转换函数指针的代码是不可移植的,通过没有传参数的函数居然可以调用这个有参数的函数,产生了不确定结果,所以建议不到万不得已不要使用reinterpret_cast转换符。

const_cast
-不相关类型转换,相当于C语言强制类型转换去掉const属性

最常用的用途就是删除变量的const属性,方便赋值。

int main()
{
    const int a = 1;
    int *p = const_cast<int*>(&a);
    *p = 2;
    cout<<a<<endl;
}

强制类型转换后大多数人无疑会以为输出2,看看结果:
这里写图片描述

为什么打印出来的是1呢?打开监视窗口瞧瞧:
这里写图片描述

好了,我来解释一下。
监视窗口看到的数据是从内存里读取到的,而打印窗口里的数据是从寄存器里读取到的。我们都知道编译器具有优化功能,当你将变量a定义为const类型,编译器认为这个数据不会再改变并且优先将其放入寄存器中。从而导致了我们明明改变了a的值却不能显式地打印出来。为了解决这个问题就要用到c++里的一个关键字。

volatile :作用防止编译器优化,直接从内存读取
这里写图片描述
c语言的强制类型转换可以达到以上三种情况的功能,对于最后一种强制类型转换特属于c++。

dynamic_cast
-用于将一个父类对象的指针转换为子类对象的指针或者引用(动态转换)

首先说明一下 向上转型:子类对象指针->父类指针/引用(不需要转换)
向下转型:父类对象指针->子类对象指针
在类的转换时,在向上转型时,dynamic_cast和static_cast的效果是一样的。在向下转型时,dynamic_cast具有类型检查的功能,比static_cast更安全。它会检查是否能够转换成功,能成功则转换,不能则返回NULL,检测在运行时进行。
这个强转有一个重要的作用,就是可以在一个继承关系里区分谁是父类谁是子类?

class AA  
{  
public:  

    virtual void fun1()  
    {  
        cout << "hello" << endl;  
    }  
public:  
    int a;  
};  

class BB :public AA  
{  
public:  

    virtual void fun1()  
    {  
        cout << "hi" << endl;  
    }  
public:  
    int b;  
};  
int main()  
{  
    AA* q = new AA();  
    BB* p = new BB();  
    AA* a;  
    BB* b;  

    b = dynamic_cast<BB*>(q);  
    if (b == NULL)  
    {  
        cout << "AA是基类" << endl;  
    }  
    else{  
        cout << "AA是子类" << endl;  
    }  

    a = dynamic_cast<AA*>(p);  
    if (a == NULL)  
    {  
        cout << "BB是基类" << endl;  
    }  
    else  
    {  
        cout << "BB是子类" << endl;  
    }  
    system("pause");  
    return 0;  
}  

这里写图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值