C++ 类型转换试验

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();     //访问错误
    }




猜你喜欢

转载自blog.csdn.net/humadivinity/article/details/80692414