stactic_cast用来执行任意明确定义的类型转换,以及反变换。但其只是暴力转换,并不负责保证转换的安全性。
1、基本数据类型之间的转换,int->char,int->enum,char->int,int->float,float->int,但精度的丢失不在static_cast的考虑范围,需要开发者自己考虑。
2、将任何非常量对象的地址存入void* & 找回存在于void*指针中的值。
char *c = new char[100];
c = "12222";
cout<<c<<endl;
这里c本身是一个指向字符数组的指针,但cout语句中,对于const char*或者 char*类型的指针,只会输出他们指向的值,而不会输出其本身存储的地址。如果想输出地址,只能显示转换一下,void* ptr = static_cast<void*>(c),此时即可输出c保存的地址;
同理也可以用static_cast进行上述过程的逆过程,如果有一个指针因为要获取地址的原因被显示转换成了void*,此时想将其转换回来,则可以这样使用:char *ptr2 = static_cast<char*>(ptr);此时cout<<ptr2;即可输出值而非地址。
char* c = new char[100];
c = "12222";
cout << "c: " << c << " ";
void* ptr1 = static_cast<void*>(c);
cout << "ptr1: " << ptr1<<" ";
char* ptr2 = static_cast<char*>(ptr1);
cout << "ptr3: " << ptr2;
cout << endl;
输出结果:
3、类层次结构中父类与子类之间指针或者引用的转换。&dynamic_cast
类中父类子类之间的指针、引用转换有两类情况,一类是从父类转换为子类,另一类是从子类转换为父类。前者叫下行转换,后者叫上行转换。上行转换较为安全,但下行转换并不安全。
A *ptr = new A;
C *cptr = static_cast<C*>(ptr);
C *dptr = dynamic_cast<C*>(ptr);//必须有多态产生,才可用dynamic_cast
cout << "cptr:" << cptr << " dptr: " << dptr;
其中类定义如下:
class A{
public:
A() = default;
virtual void func(){}
int m; };
class B{ int m; };
class D{
virtual void func(){};
};
class C :public A, B{
public:
int temp;
};
由于类的继承关系,指向父类指针既可以指向子类对象,也可以指向子类对象。但子类指针不可指向父类对象,这就是问题所在。
上述情况即一个指向父类对象的父类指针,被强制转换为一个指向父类对象的子类指针,因为子类中可能有父类中没有的属性与函数,如果用转换过后的指针去访问子类专属的成员,那就会造成访问越界,内存崩溃。如果使用static_cast强行转换,程序不会报错,也不会做运行时类型检查,这就是一个巨大的隐患。
dynamic_cast所做的就是在运行时进行类型检查,此时,检测到这样的转换不合适,就会将转换后的指针置NULL,保证程序不会崩溃。
因为引用没有NULL引用,所以dynamic_cast引用遇到此类情况,就会抛出std::bad_cast异常。
tip:static_cast & dynamic_cast可以做从非const类型到const类型,但反之不行。