C++小点之四种强制类型转换

提问:

1.为什么要搞出四种,用原先使用的那种不可以吗?

答:因为强制类型转换时是具有一定的风险的,这种风险包括(精度的损失 ,派生类与基类的一些转换关系) 而且根据风险程度的不同导致的 bug 也会不同 ,再加上存在许多种类型之间的转换 ,
所以C++选择将其分为四种 。

2.这样分类之后又有什么好处呐?

答:关于这个问题,让我们来设想一个场景。假如你现在知道你的bug 是因为指针类型之间的转换所导致的 ,那你现在就必须得定位它/它们 ,如果还用以前的那种方式,就会找到许多无关于这次需求的东西,如果使用C++的这种方式,你只需要去找所对应的 _cast 就行了 。很方便吧 😃

四种强制类型转换:static_cast , reinterpret_cast ,const_cast和 dynamic_cast

(1)static_cast

<1>适用:用来进行比较“自然”和低风险的转换 。比如:整型与实数,字符型之间的转换

<2>不适用:不同类型指针,整型与指针,不同类型引用之间的转换 。

#include<iostream>
using namespace std;
class A
{
public:
	operator int(){return 1 ;} //注意这里!!!!
	operator char *(){return nullptr ;}
};
int main(int argc, char const *argv[])
{
	A a ;
	int n ; 
	char *p= "Liu Shengxi ";
	n= static_cast<int>(3.14); // 3
	cout << n << endl ;
	n = static_cast<int>(a) ; // 1 
	cout << n << endl ;

	p = static_cast<char *>(a);/*从类型‘int’到类型‘char*’中的 static_cast 无效*/
	
	return 0;
}

(2)reinterpret_cast

<1>适用:用来进行各种**不同类型的指针,引用,以及指针和能容纳的下指针的整数类型之间的转换。**转换方式:逐个拷贝比特

#include<iostream>
using namespace std ;
class A
{
public:
	int i ;
	int j ; 
	A(int n):i(n),j(n){}
};
int main(int argc, char const *argv[])
{
	A a(100);
	int &r = reinterpret_cast<int &>(a);//引用之间的转换
	r =  200 ; 
	cout << a.i <<" ," << a.j << endl ;
	int n = 300 ; 
	A *pa =reinterpret_cast< A *>(& n);
	pa-> i = 400 ; // n 变为 400 
	pa->j = 500 ; //不安全,容易导致程序崩溃
	cout << "n== " << n << endl ;

    typedef void (*PF1)(int) ;
    typedef int (*PF2)(int ,char *);
    PF1 pf1  ;
    PF2 pf2 ;
    pf2 = reinterpret_cast<PF2>(pf1 );//不同类型的函数指针也可以互相转换
	return 0;
}

<2>不适用:

(3)const_cast

<1>适用:用来去除const 属性 ,将const 引用或者const 指针转换为同类型的非const类型 。

<2>不适用:

const string s= "TT";
string &p = const_cast<string &>(s) ;
string *pp = const_cast<string *>(&s) ;//&s 就是const string * 

(4)dynamic_cast

<1>适用:**专门用于将多态基类(包含虚函数的基类)的指针/引用强制转换为派生类指针/引用 **。而且能够检查转换的安全性。对于不安全的指针转换,返回 NULL指针。

<2>不适用:

#include<iostream>
using namespace std;
class Base
{
    public:
    virtual ~Base(){} //有虚函数,所以是多态基类
};
class Derived:public Base
{  
};
int main(void){
    Base b; 
    Derived d ;
    Derived *pd ;
    pd = reinterpret_cast<Derived *>(&b ) ; //reinterpret_cast 不检查安全性,总是进行转换
    if(pd == NULL ) 
        cout << "1111 " << endl; 

    pd = dynamic_cast<Derived *>(&b ); //转换会失败 ,因为&b 并没有实际指向一个派生类对象 
    if(pd == NULL )
        cout << "unsafe dynamic_cast  " << endl; 
    Base *pb = &d ;

    pd = reinterpret_cast<Derived *>(pb );//成功
    if(pd == NULL )
        cout << "unsafe dynamic_cast  " << endl; 
    else 
        cout << "safe dynamic_cast  " << endl; 
    return 0 ;
}

总结:

###1.基类指针向派生类指针的转换取决于这个基类指针是不是真的指向一个派生类对象 ,如果是,那转换之后完全OK,如果不是,那么将它强制转换为派生类指针时就会出现问题 。

2. 关于指针的有dynamic_cast 和 interpret_cast 。其中dynamic_cast 只用于多态基类

3. const_cast 用来去除const 属性

4. static_cast 无关于指针和引用

posted @ 2018-05-10 15:47  Tattoo_Welkin  阅读(123)  评论(0编辑  收藏  举报