C++中四种强制类型转换的方式
参考引用:C++强制类型转换操作符 dynamic_cast - 狂奔~ - 博客园 (cnblogs.com)
【C++】static_cast基本用法(详细讲解)_c++ static_cast-优快云博客
1、static_cast
用法场景
(1)用于基本数据类型之间的转换,比如将double转换为int,float转换为double等。
double d = 5.5;
int i = static_cast<int>(d); // i = 5
(2)将指向派生类的指针转换为基类的指针,也就是上行转换,编译器会在编译的时候检查这个派生类是否是基类的子类,所以转换的过程是安全的。
class Base {};
class Derived : public Base {};
Derived derivedObj;
Base* basePtr = static_cast<Base*>(&derivedObj);
(3)将指向基类的指针转换为派生类的指针,也就是下行转换,编译器没有进行动态类型检查,所以是不安全的,应该使用dynamic_cast
Base* basePtr = new Base();
Derived* derivedPtr = static_cast<Derived*>(basePtr); // 不安全!
(4)在有关联的类型之间进行转换,比如转换枚举值为整数
enum Color { RED, GREEN, BLUE };
int value = static_cast<int>(GREEN); // value = 1
(5)将其它类型的指针转换为void*指针,比如将int类型的指针转换为void型的指针
int *a;
void* b = static_cast<void*>a;
2、const_cast
用法场景
#include<iostream>
using namespace std;
int main()
{
int a = 10;
const int * p = &a; //常量指针
//*p = 20;//报错,常量指针不能修改指向的内容
int *q;
q = const_cast<int *>(p);
*q = 20; //使用const_cast转换之后,可以修改
cout <<a<<" "<<*p<<" "<<*q<<endl;
cout <<&a<<" "<<p<<" "<<q<<endl;
//指向的地址一样
return 0;
}
注意
1、const_cast无法去除变量的常量性,如下所示:
const int a = 10;
int b = const_cast<int>(a); //compile error
2、使用时要注意,将常量指针进行常量性去除赋值给别的指针之后,别的指针就和原指针共享这块内存,这块内存就不安全了,所以要小心使用
3、reinterpret_cast
用法场景
(1)指针之间类型的转换
int *a = new int;
double *d = reinterpret_cast<double *>(a);
(2)指针转换成整形,但是要注意转换的时候一定要转换到足够长的整形类型中,指针在16、32、64位操作系统下大小分别为2、4、8字节,所以在转换的时候至少要转换到对应大小的整形。
//在64位系统下测试
int b = 0;
int* a = &b;
cout<<__SIZEOF_INT__<<endl; //4
cout<<__SIZEOF_LONG__<<endl; //8
cout<<__SIZEOF_POINTER__<<endl; //8
//int convertedValueint = reinterpret_cast<int>(a); //错误,因为指针大小为8字节,int大小只为4字节
long convertedValue = reinterpret_cast<long>(a); // 将 int* 指针转换为 long正确
(3)整形转换为指针
int b = 0;
int* a = reinterpret_cast<int*>(b);
4、dynamic_cast
前面我们讲到了static_cast无法保证类内下行转换的安全性,dynamic_cast就做到了动态类型检查,所以就能够保证下行转换的安全性。下行转换又分两种情况,一种是基类指针指向派生类型,然后进行转换,这种转换是安全的,第二种情况是基类指针指向基类类型,这种转换就需要进行动态运行检查,转换失败,会返回NULL。
#include "stdafx.h"
#include<iostream>
using namespace std;
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";}
};
int main()
{
//这是第一种情况
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;
}
delete(base);
delete(base1);
system("pause");
}
上面代码中,第二种情况将会转换失败,因为第二种情况的基类指针指向了基类,dynamic_cast只有基类指针指向派生类的时候,才能转换成功。还有个要注意的点是在类层次之间进行指针转换的时候,dynamic_cast只能在具有多态性的类层次结构中进行向下转换,也就是基类至少要含有一个虚函数。
引用的转换规则与指针的转换规则类似,但是引用转换失败并不会返回null,因为没有空引用的概念,引用转换失败会抛出一个bad_cast的异常