C++ 类型转换试验

转载自:https://blog.youkuaiyun.com/humadivinity/article/details/80692414

C++的四个类型转换,以下只是进行了试验而已,原理有待发掘


1、static_cast

静态类型转换,

(1)在转换的两边都是基本类型的时候,感觉和C风格的强制类型转换差不多。

float fValue = 6.5;
int i = static_cast<int>(fValue);
printf("i = %d\n", i);    //输出 i= 6


(2)当转换类型为类类型的时候,在会进行一次编译器的类型检查,假设有如下代码:

    class Father
    {
    protected:
        void ProtecFunc(){ printf("this is father protect function.\n"); }
    public:
        void name(){ printf("this is father.\n"); }
        virtual void callme(){ printf("this is father call.\n"); }
    };
     
    class Son : public Father
    {
    public:
        void name(){ printf("this is SON.\n"); }
        virtual void callme(){ printf("this is SON call.\n"); }
    };
     
    class Other
    {
    public:
        void name(){ printf("this is Other.\n"); }
        virtual void callme(){ printf("this is Other call.\n"); }
    };

在进行静态类型转换的时候,编译器会对两边的类型进行检查,只有“有继承关系”的类才能通过这个检查:

    Father *pFa = new Father();    
    Son* pSon = static_cast<Son*>(pFa);
    pSon->name();               //输出 "this is SON"
    pSon->callme();             //输出   “this is father call”
 
    Son* pSon1 = new Son();
    Father *pFa1 = static_cast<Father*>(pSon1);
    pFa1->name();           // 输出 "this is father"
    pFa1->callme();          //输出  “this is SON call”
 
    Other* pOther = new Other();
    Father* pSon2 = static_cast<Father*>(pOther);   //无法编译通过


2、const_cast

常量类型转换,const_cast 中的类型必须是指针、引用或指向对象类型成员的指针。

(1)基本类型是无法使用的,如:

        int nValue = 5;
        const int nCValue = const_cast<int>(nValue);   //无法编译通过

(2)只能在同类型间使用, 其只能调节类型限定符const ,而不能更改基础对象类型

    //可以编译通过,并正常输出
    Father* pFa = new Father();
    Father  * const pFa1 = const_cast<Father*>(pFa);           
    pFa1->name(); 
    pFa1->callme();
    Father* pFa = new Father();
    Father const * pFa2 = const_cast<Father*>(pFa);
    pFa2->name();       //该行报错
    //无法编译通过, 编译器给出的错误是 :
    //    1 	error C2662 : “void Father::name(void)” : 不能将“this”指针从“const Father”转换为“Father &”
    //    2	IntelliSense : 对象包含与成员函数不兼容的类型限定符            对象类型是 : const Father
    Son* pSon = new Son();
    Father  * const pFa2 = const_cast<Father*>(pSon);      
 //无法编译通过, 只能调节类型限定符, 不能更改基础类型
    const Father*  pFa = new Father();
    //Father  *pFa1 = pFa;        //无法编译通过, 无法从“const Father *”转换为“Father *”
    Father  *pFa1 = const_cast<Father*>(pFa);    //编译通过

3、dynamic_cast:动态类型转换

(1) dynamic_cast 中的类型必须是指向完整类类型或 void * 的指针或引用,对基本类型使用时,是无法编译通过的

int iValue = 5;
float fValue = dynamic_cast<int>(iValue);       //无法编译通过

(2)在运行时检查对象类型, 只有“存在继承关系”的对象间可以使用,子类对象可以转为父类对象,但父类对象无法转为子类对象

    Father *pFa = new Father();
    Son* pSon = dynamic_cast<Son*>(pFa);
    if (pSon)
    {
        //不会进入这里执行
        pSon->name(); 
        pSon->callme(); 
    }
 
    Son* pSon1 = new Son();
    Father *pFa1 = dynamic_cast<Father*>(pSon1);
    if (pFa1)
    {
        //进入执行
        pFa1->name();           // 输出 "this is father"
        pFa1->callme();          //输出  “this is SON call”
    }
 
    Other* pOther = new Other();
    Father* pFa2 = dynamic_cast<Father*>(pOther);
    if (pFa2)
    {
        //不会进入执行
        pFa2->name();
        pFa2->callme();
    }
 
    OtherNoVirtual* pOtherNoVirtual = new OtherNoVirtual();
    Father* pFa3 = dynamic_cast<Father*>(pOtherNoVirtual);   //无法编译通过, 运行时 dynamic_cast 的操作数必须包含多态类类型


4、interpret_cast

这个使用起来和C风格的强制转换很像,既可用于基础类型,也可用于对象类型,不做任何检查,不改变值,
具体区别望大神指教:

    char* pszValue = "hello.";
    float fValue = reinterpret_cast<float&>(pszValue);
    int iValue = reinterpret_cast<int&>(pszValue);
    printf("fValue = %f, iValue=%x, pointer = %p\n", fValue, iValue, pszValue);
    //输出 fValue = 0.000000, iValue=871988, pointer = 00871988
 
    Father *pFa = new Father();
    Son* pSon = reinterpret_cast<Son*>(pFa);
    if (pSon)
    {
        //不会进入这里执行
        pSon->name();       //输出 "this is SON"
        pSon->callme();      // 输出 "this is father call"
    }
 
    Son* pSon1 = new Son();
    Father *pFa1 = reinterpret_cast<Father*>(pSon1);
    if (pFa1)
    {
        //进入执行
        pFa1->name();           // 输出 "this is father"
        pFa1->callme();          //输出  “this is SON call”
    }
 
    Other* pOther = new Other();
    Father* pFa2 = reinterpret_cast<Father*>(pOther);
    if (pFa2)
    {
        //很危险,当成另一个对象来用了
        pFa2->name();           // 输出 "this is father"
        pFa2->callme();         //输出  “this is Other call”
    }
 
    OtherNoVirtual* pOtherNoVirtual = new OtherNoVirtual();
    Father* pFa3 = reinterpret_cast<Father*>(pOtherNoVirtual); 
    if (pFa3)
    {
        //这很危险,因为相当于使用不存在的空间
        pFa3->name();         //输出 "this is father"
        pFa3->callme();     //访问错误
    }

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值