C++ – const_cast, static_cast, dynamic_cast, reinterpret_cast四种cast转换的区别和使用
在C++中有四种形式的cast:const_cast、static_cast、dynamic_cast、reinterpret_cast。本篇文章将介绍什么时候和怎么样去使用这四种不同的cast。
1 const_cast
const_cast用于将一个const常量转换为变量,或者将一个变量转为const常量,即可以去除或者添加变量的常量性。
但是因为const_cast这一特性,应该尽量减少使用const_cast,如果一定要将一个const常量修改为一个变量,也要确定这种行为是正确的。
比如说
#include <iostream>
using namespace std;
// 1. Using a const_cast for a reference
void ExampleConstCast1(const int& value)
{
// remove const specifier, access value
int& ref = const_cast<int&> (value);
ref = 20; // through a reference to a constant value, you can access value
// value = 50; - not allowed, expression must be a modifiable lvalue
}
// 2. Using const_cast for a reference
void ExampleConstCast2(const int& value)
{
// remove the const modifier from the value
const_cast<int&> (value) = value + value;
}
// 3. Applying const_cast to a pointer
void ExampleConstCast3(const int* x)
{
int* p = const_cast<int*> (x); // remove const from x
*p = 100;
}
void main()
{
// Demonstration of using the const_cast modifier
int t = 30;
ExampleConstCast1(t);
cout << "t = " << t << endl; // t = 20
ExampleConstCast2(t);
cout << "t+t = " << t << endl; // t = 20+20 = 40
int x = 50;
ExampleConstCast3(&x);
cout << "x = " << x << endl; // x = 100
}
程序输出
t = 20
t+t = 40
x = 100
2 static_cast
static_cast主要有如下几种用法:
- 用于类层次结构中基类和子类之间指针或引用的转换。进行上行转换(把子类的指针或引用转换成基类)是安全的;进行下行转换(把基类指针或引用转换成子类指针或引用)时,由于没有动态类型检查,所以是不安全的。
- 用于执行普通类型之间的隐式转换,比如将int转为float,char转为int
- 将一个指针转换为void*,或者将void*转换为目标指针(不安全)
- 将任何类型转为void类型
比如说:
普通类型转换
float a = static_cast<float>(5);
int b = static_cast<int>(9.63);
指针类型转换
OnEventData(void* pData)
{
EventData *evtdata = static_cast<EventData*>(pData);
}
3 dynamic_cast
dynamic_cast专门用于处理多态类型,多态类型是指父类至少有一个声明或者继承的虚函数。
dynamic_cast使用运行时类型信息确定强制转换是否有效,与其他类型转换不同,dynamic_cast存在运行时开销。
dynamic_cast主要是在运行时将指针/引用在继承层次结构中安全的进行向上转换、向下转换、横向转换。如果指针类型转换失败将返回nullptr,如果引用类型失败则抛出std::bad_cast
异常.
dynamic_cast主要是用在进行向下转换,基类转换到派生类安全转换中:
- Derived * ptr_derived = dynamic_cast < Derived * > ( ptr_base )
- Derived & ref_derived = dynamic_cast < Derived & > ( ref_base )
而向上转换,从派生类转换为基类则是安全的。
dynamic_cast在类层次间进行向上转换时,dynamic_cast和static_cast的效果是一样的;但是在进行向下转换时,dynamic_cast具有类型检查的功能,比static_cast更安全。
首先,dynamic_cast不能用于不是多态类型的转换,比如
#include<iostream>
using namespace std;
class Base // 父类
{
};
class Child :public Base { // 子类
};
int main()
{
Base* b_ptr = new Child();
Child* c_ptr = dynamic_cast<Child*>(b_ptr);
}
编译错误,提示
error C2683: “dynamic_cast”:“Base”不是多态类型
我们来通过以下代码看dynamic_cast的用法:
- 情况1,当基类指针实际上指向基类,使用dynamic_cast进行向下转换时,这个转换是不安全的
- 情况2,当基类指针实际上指向派生类,使用dynamic_cast进行向下转换时,转换成功
- 情况3,当子类指针实际上指向子类,使用dynamic_cast进行向上转换时,转换成功
#include<iostream>
using namespace std;
class Base // 父类
{
public:
virtual void f()
{
cout << "this is base class !" << endl;
}
};
class Child :public Base { // 子类
public:
void f()
{
cout << "this is child class !" << endl;
}
};
int main()
{
//情况1
Base* b_ptr0 = new Base(); // 指向父类的父类指针
Child* c_ptr0 = dynamic_cast<Child*>(b_ptr0);// 下行转换,此时由于父类指针实际上是指向父类的,
//这个转换不安全,所以c_ptr0的值为nullptr
if (!c_ptr0)
{
cout << "can not cast the type !" << endl; // 代码会走到这里
}
else
{
c_ptr0->f();
}
//情况2
Base* b_ptr = new Child();// 指向子类的父类指针
Child* c_ptr = dynamic_cast<Child*>(b_ptr); // 下行转换,此时由于父类指针实际上是指向子类的
//所以这个转换是可以的
if (!c_ptr)
{
cout << "can not cast the type !" << endl;
}
else
{
c_ptr->f();// 代码会走到这里
}
//情况3
Child* c_ptr1 = new Child();// 指向子类的子类指针
Base* b_ptr1 = dynamic_cast<Base*>(c_ptr1); // 将子类转换为父类是安全的,上行转换一定是允许的
if (!b_ptr1)
{
cout << "can not cast the type !" << endl;
}
else
{
b_ptr1->f();// 代码会走到这里
}
}
程序输出
can not cast the type !
this is child class !
this is child class !
4 reinterpret_cast
reinterpret_cast将一种类型直接强制转换为另一种类型,比如将一种指针直接转换为另一种指针,将一种类型直接转换为int。
与static_cast相比,reinterpret_cast的功能更加强大,安全性更低,对使用者的技术能力要求很高。
这个和const_cast一样,谨慎使用。
#include <iostream>
using namespace std;
void main()
{
// 1. Convert char* => int
int number;
const char* pStr = "Hello world!";
// get a pointer to str as an integer
number = reinterpret_cast<int> (pStr);
cout << "number = " << number << endl;
// 2. Convert int => double*,
// convert integer to pointer
unsigned int num = 300;
double* p;
p = reinterpret_cast<double*> (num);
cout << "p = " << p << endl;
}
程序输出
number = -1184584664
p = 000000000000012C
5 总结
对于上述四种cast,我们可以得出以下结论
- const_cast通常用于去除常量的const属性
- static_cast可以实现父类与继承子类之间的上行或者下行转换,但是不保证安全;可以进行普通类型转换,比如int转float;可以进行其他类型指针与void*类型的转换,不保证安全;
- dynamic_cast主要用在存在多态类的转换,用于保证安全转换
- reinterpret_cast用于在两个类型之间进行强制转换,不管这两个类型是否有关联,是最不安全的cast
参考链接
本文作者:StubbornHuang
版权声明:本文为站长原创文章,如果转载请注明原文链接!
原文标题:C++ – const_cast, static_cast, dynamic_cast, reinterpret_cast四种cast转换的区别和使用
原文链接:https://www.stubbornhuang.com/2756/
发布于:2023年08月17日 15:37:06
修改于:2023年08月17日 15:38:56
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。
评论
50