Loading

4-11.3 C++中的显式类转换

static_cast

1.用来改变基本类型:一般是高精度转低精度

显示地告诉程序阅读者和编译器,不考虑高精度想低精度转换时造成的精度损失

#include<iostream>
using namespace std;
int main(){
    double d = 2.1;
    int i = 6;
    int res = i/d;  //i被隐式地转换为double res=6/2.1 = 2
    cout<<res<<endl;  //输出2
    res = i/static_cast<int>(d); //d被强制转换为int res = 6/2 = 3
    cout<<res<<endl;  //输出3
    return 0;
}

2.恢复void* 指针类型

#include<iostream>
using namespace std;
int main(){
    int i = 2;
    void *p = &i;  //无法通过p得到它所指对象的值
    int *q = static_cast<int*>(p);  //将其转换为int*,得到其所指向的值
    cout<<*q<<endl;  //输出2
    return 0;
}

注意:void*在强制类型转换时只能转换为原来的对应类型,如例子中,只能转换为int*,否则会产生未定义行为

const_cast

用来去除底层const(low-level const)

#include<iostream>
using namespace std;
int main(){
    const char *pc;
    char *p = const_cast<char*>(pc);  //把pc的底层const去除,否则无法对p进行初始化(p不是const)
    int *ip = static_cast<int*>( const_cast<char*>(pc)); //去除const后再改变基本类型
    return 0;
}

注:1.const_cast可以去除底层const,但不代表转换后的指针可以改变其指向的值,如果*p是一个const对象,依然不能用p改变其值

2.const_cast只能去除const,不能改变对象的原类型,const_cast<string>(pc);是不行的,改用static_const<string>(pc);

const_cast在函数重载时运用广泛

reinterpret_cast

为运算对象的位模式提供较低层次的重新解释,但并不真正改变对象类型

#include<iostream>
using namespace std;
int main(){
    int *ip;
    char *pc = reinterpret_cast<char*>(ip);  //pc所指的真实对象实际上是int类型而不是字符
    string s(pc);  //用int*来初始化string显然会出现问题,但由于有显示类型转换,所以编译器不会报错
    cout<<s<<endl;
    return 0;
}

使用reinterpret_cast是非常危险的,用pc初始化str的例子很好地证明了这一点。其中的关键问题是类型改变了,但编译器没有给出任何警告或者错误的提示信息。当我们用一个int的地址初始化pc时,由于显式地声称这种转换合法,所以编译器不会发出任何警告或错误信息。接下来再使用pc时就会认定它的值是char*类型,编译器没法知道它实际存放的是指向int的指针。最终的结果就是,在上面的例子中虽然用pc初始化 str 没什么实际意义,甚至还可能引发更糟糕的后果,但仅从语法上而言这种操作无可指摘。查找这类问题的原因非常困难,如果将ip 强制转换成pc的语句和用pc初始化 string对象的语句分属不同文件就更是如此。

所以在编程时经历避免强制类型转换

旧式类型转换

(type)expr:c语言风格的函数类型转换,其含义并不清晰,根据语境会分别具有static\_castconst\_castreinterpret\_cast的功能。

int *ip;
char *pc = (char*)ip;  //作用同reinterpret_cast

所以追踪错误时会更加困难,不建议使用。

posted @ 2022-01-18 11:50  咪啪魔女  阅读(44)  评论(0编辑  收藏  举报