dynamic_cast
:有虚函数的类,指针或引用,类层次结构中进行转换(主要是向上转换);const_cast
:去掉 const 或 volatile 属性;static_cast
:编译期间转换,没有运行时类型检查来保证转换的安全性;reinterpret_cast
:仅仅重新解释类型,没有对数据进行调整。
dynamic_cast
static_cast < new_type > ( expression )
dynamic_cast
动态类型转换,用于实现RTTI。只能用于含有虚函数的类,用于类层次间的向上和向下转化。只能转指针或引用。向下转化时,如果是非法的对于指针返回NULL,对于引用抛异常bad_cast
-
只能用于有虚函数的类;
-
只能用于指针或引用;
-
对运行期类型信息(RTTI)进行了检查,类层次结构中向上转换成功,其余转换返回空指针;
若是基类指针指向派生类对象,再将基类指针向下转型,成功!
#include <iostream>
using namespace std;
class A{
public:
virtual void func() const { cout<<"Class A"<<endl; }
};
class B: public A{
public:
virtual void func() const { cout<<"Class B"<<endl; }
};
class C: public B{
public:
virtual void func() const { cout<<"Class C"<<endl; }
};
class D: public C{
public:
virtual void func() const { cout<<"Class D"<<endl; }
};
int main(){
A *pa = new A();
//情况①
B *pb = dynamic_cast<B*>(pa); //向下转型失败 赋值NULL
C *pc = dynamic_cast<C*>(pa); //向下转型失败 赋值NULL
//情况②
pa = new D(); //向上转型都是允许的
pb = dynamic_cast<B*>(pa); //向下转型成功
pc = dynamic_cast<C*>(pa); //向下转型成功
return 0;
}
const_cast
const_cast < new_type > ( expression )
修改类型的 const
或 volatile
属性。除了 const 或 volatile 修饰之外, new_type 和 expression 的类型必须是一样的。
函数指针和成员函数指针不可用于 const_cast
expression 内存空间是只读的,转换类型后,只能读,不能写。转换后的指针或引用能修改值,源数据值却未改变,但是他们的地址是同一个!!!。
#include<iostream>
int main() {
int i = 3; // 不声明 i 为 const
const int& rci = i;
const_cast<int&>(rci) = 4; // OK:修改 i
std::cout << "i = " << i << std::endl; // i = 4
const int c_val = 233; //声明为常量类型
int &use_val = const_cast<int&>(c_val); //使用去const 引用
int *ptr_val = const_cast<int*>(&c_val);//使用去const 指针
std::cout << "&c_val = " << &c_val << std::endl;
use_val = 111; //未定义行为
std::cout << c_val << "\t" << use_val << "\t" << *ptr_val << "\t&use_val = " << &use_val << std::endl;
*ptr_val = 222; //未定义行为
std::cout << c_val << "\t" << use_val << "\t" << *ptr_val << "\tptr_val = " << ptr_val << std::endl;
// std::cout << "&c_val = " << &c_val << std::endl;
return 0;
}
/* https://zh.cppreference.com/w/cpp/language/const_cast 输出为
i = 4
&c_val = 0x7ffd3abc86cc
233 111 111 &use_val = 0x7ffd3abc86cc
233 222 222 ptr_val = 0x7ffd3abc86cc
*/
static_cast
static_cast < new_type > ( expression )
static_cast
作用和C语言风格强制转换的效果基本一样,由于没有运行时类型检查来保证转换的安全性,所以这类型的强制转换和C语言风格的强制转换都有安全隐患。static_cast
是“静态转换”的意思,也就是在编译期间转换,转换失败的话会抛出一个编译错误。
- 能使用隐式转换的地方,均可以使用
static_cast
转换; - 用于基本数据类型之间的转换,如把int转换成char,把int转换成enum。这种转换的安全性也要开发人员来保证;
- 如果类型不兼容,使用
static_cast
编译检查,会报错; - 类层次结构中基类(父类)和派生类(子类)之间指针或引用的转换。向上转换是安全的,向下转换不安全;
- 把void指针转换成目标类型的指针(不安全!!);
- 把任何类型的表达式转换成void类型。
//下面是正确的用法
int m = 100;
long n = static_cast<long>(m); //宽转换,没有信息丢失
char ch = static_cast<char>(m); //窄转换,可能会丢失信息
int *p1 = static_cast<int*>( malloc(10 * sizeof(int)) ); //将void指针转换为具体类型指针
void *p2 = static_cast<void*>(p1); //将具体类型指针,转换为void指针
//下面的用法是错误的
float *p3 = static_cast<float*>(p1); //不能在两个具体类型的指针之间进行转换
p3 = static_cast<float*>(0X2DF9); //不能将整数转换为指针类型
// 上行 Sub -> Base
//编译通过,安全
Sub sub;
Base *base_ptr = static_cast<Base*>(&sub);
// 下行 Base -> Sub
//编译通过,不安全
Base base;
Sub *sub_ptr = static_cast<Sub*>(&base);
reinterpret_cast
reinterpret_cast< new_type > ( expression )
用于高度危险的类型转换,仅仅是对二进制位的重新解释,不会对数据进行调整。
char *p1 = "hello world";
int *p2 = reinterpret_cast<int *>(p1);