c++中的四种cast转换

更新时间:2020-01-19 11:18:21 点击次数:1376次
本章主要复习的是 类型之间的互相转换,类型好端端的为什么就要转换呢?因为像 C++ 语言是强类型的语言,所以在赋值或者运算的时候类型需要转换一致

那么在C语言中存在着隐式转换和显示转换着两种

// 隐式类型转换
int i = 1;
double d = i;

// 显示的强制类型转换
int* p = &i;
int address = (int)p;
printf("%x, %d\n", p, address);

缺陷: 转换的可视性比较差,你容易忽视它的转换,所有的转换形式都是以一种相同的形式书写,难以跟踪错误

所以引出了 C++强制类型转换

标准C++为了 加强类型转换的可视性 让你明确的知道,原来这个变量,这个类型已经转换为另一种类型了,就引入了四种命名的强制类型转换操作符:static_cast、reinterpret_cast、const_cast、dynamic_cast

当然这篇重要掌握的就是他们之间的区别?

static_cast 可以实现 C++内置基本类型的转换;

double d = 12.34;
int a = static_cast<int>(d); // a = 12

它也可以实现具有继承关系类型之间的转换

class Base{};
class Derived :public Base{};

Derived d;
Base e = staic_cast<Base>(d);

我们可以看出它是从派生类对象转换为基类对象,那么反过来可以吗?可以把基类对象转换为派生类对象吗?

不可以,编译器不允许我们这样做,因为会不安全!

试想如果把基类转换为派生类型的话,因为派生类可能会派生出基类没有的东西,所以如果让转换的那个对象去访问派生类成员,这个成员在基类可能不存在,这样就会引发错误!

dynamic_cast 和 static_cast 是相对的,static_cast 是在编译的时候进行转换的。它是动态的在运行时候转换的,而且 只能在继承类对象的指针或引用之间进行转换,在进行转换的时候,会根据当前RTTI (运行时类型识别)判断类型对象之间的转换是否合法,如果合法就转换成功了,返回了指向类的引用或指责,但是如果转换是非法的,则返回NULL或者0

使用 dynamic_cast 进行转换的时候,基类一定要有虚函数,另外它向上转换的时候是兼容的,向下转换的时候有类型安全检查,比static_cast 要安全

class A {
public:
virtual void f() {}
};
class B : public A
{};

void fun(A* pa) {
// dynamic_cast会先检查是否能转换成功,
// 能成功则转换,不能则返回0
cout << "pa" <<' '<< typeid(pa).name()<<pa << endl;

B* pb1 = static_cast<B*>(pa);
B* pb2 = dynamic_cast<B*>(pa);
//pa   class A*  00AFFE00
//pb1  class B*  00AFFE00
//pb2  class B*  00000000 

//pa   class A*  00AFFDF4
//pb1  class B*  00AFFDF4
//pb2  class B*  00AFFDF4
cout << "pb1" <<' '<<typeid(pb1).name()<<' '<< pb1 << endl;
cout << "pb2" <<' '<<typeid(pb2).name()<<' '<< pb2 << endl;
}
int main() {
A a;
B b;
fun(&a);
fun(&b);
system("pause");
return 0;
}

reinterpret_cast 类型转换函数 将一个类型的指针转换为另一个类型的指针。reinterpret 单词的汉语意思是重新解释,所以这种转换不需要修改指针变量值数据存放格式,只需在编译时重新编译解释指针的类型即可

就像这样

double d = 9.3;
double *pd = &d;
int *pi = reinterpret_cast<int*>(pd);

上面是将 double * 转换为 int * ,但是不可以用于非指针类型的转换,reinterpret_cast 同时也不能将一个const指针转换为void*指针

reinterpret_cast 这里是将一个整形函数转换为函数指针的类型去调用,但是存在着缺陷(了解)

typedef void(*FUNC)();
int DoSomething(int i){
cout << "DoSomething" << endl;
return 0;
}

void Test(){
// reinterpret_cast可以编译 
// 以FUNC的定义方式去看待DoSomething函数
// 所以非常的BUG,下面转换函数指针的代码是不可移植的,
// 所以不建议这样用

// C++不保证所有的函数指针都被一样的使用,
// 所以这样用有时会产生不确定的结果
FUNC f = reinterpret_cast<FUNC>(DoSomething);
f();
}

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

const int* pci = 0;
int* pj = const_cast<int*>(pci);
1
2
经过转换后的 pci 赋值给pj ,不在具备常量的属性,可以被修改

本站文章版权归原作者及原出处所有 。内容为作者个人观点, 并不代表本站赞同其观点和对其真实性负责,本站只提供参考并不构成任何投资及应用建议。本站是一个个人学习交流的平台,网站上部分文章为转载,并不用于任何商业目的,我们已经尽可能的对作者和来源进行了通告,但是能力有限或疏忽,造成漏登,请及时联系我们,我们将根据著作权人的要求,立即更正或者删除有关内容。本站拥有对此声明的最终解释权。

回到顶部
嘿,我来帮您!