zoukankan      html  css  js  c++  java
  • static_cast dynamic_cast const_cast reinterpret_cast总结对比

    【本文链接】

    http://www.cnblogs.com/hellogiser/p/static_cast-dynamic_cast-const_cast-reinterpret_cast.html

    【分析】

    旧式风格 vs C++风格

     C++ Code 
    1
    2
    3
    4
    5
    6
    7
     
    (new_type) expression   // c-style
    new_type (expression)  // function-style

    dynamic_cast <new_type> (expression)
    reinterpret_cast <new_type> (expression)
    static_cast <new_type> (expression)
    const_cast <new_type> (expression)

    【static_cast】

    用于基本数据类型之间的转换,如把int转换成char,把int转换成enum,这种转换的安全性也要开发人员来保证。

     C++ Code 
    1
    2
    3
    4
    5
    6
    7
    8
     
    // basic type cast
    enum e { A = 1, B, C };
    double d = 12.25;
    unsigned int ui = 25;
    char c = static_cast<char>(ui);
    int i = static_cast<int>(d);
    int j = static_cast<int>(B);
    double k = static_cast<double>(ui);

    用于类层次结构中基类和子类之间指针或引用的转换。(非多态类型转换,没有virtual)

    • 进行上行转换(把子类的指针或引用转换成基类表示)是安全的;
    • 进行下行转换(把基类指针或引用转换成子类表示)时,转换是合法的,但是由于没有动态类型检查,所以是不安全的。
     C++ Code 
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
     
    /*
        version: 1.0
        author: hellogiser
        blog: http://www.cnblogs.com/hellogiser
        date: 2014/9/22
    */


    #include "stdafx.h"
    #include "iostream"
    using namespace std;

    class Base
    {
    public:
        Base(): n1(
    0) {}
        
    int n1;
    };

    class Derived: public Base
    {
    public:
        Derived(): n2(
    0) {}
        
    int n2;
    };


    void test_static_cast()
    {
        Base *p = 
    new Base();
        Derived *pb = 
    static_cast<Derived *>(p);
        cout << pb->n1 << endl; 
    // 0  ok
        cout << pb->n2 << endl; // -33686019   (not safe)
        delete p;
    }

    int main()
    {
        test_static_cast();
        
    return 0;
    }

    【dynamic_cast 】

    用法:dynamic_cast < type-id > ( expression )
    该运算符把expression转换成type-id类型的对象。Type-id必须是类的指针、类的引用或者void *;
    如果type-id是类指针类型,那么expression也必须是一个指针,如果type-id是一个引用,那么expression也必须是一个引用。

    dynamic_cast主要用于具有Virtual函数类层次间的上行转换和下行转换,还可以用于类之间的交叉转换。(多态类型转换,必须要有virtual)

    • 在类层次间进行上行转换时,dynamic_cast和static_cast的效果是一样的;
    • 在进行下行转换时,dynamic_cast具有类型检查的功能,并且要求基类具有virtual函数,比static_cast更安全。(如果指针能够不能够正确转换,返回NULL;如果引用不能正确转换,则抛出bad_cast异常)
     C++ Code 
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
     
    /*
        version: 1.0
        author: hellogiser
        blog: http://www.cnblogs.com/hellogiser
        date: 2014/9/22
    */


    #include "stdafx.h"
    #include "iostream"
    using namespace std;

    class Base
    {
    public:
        Base(): n1(
    0) {}
        
    virtual void fun()
        {
            cout << 
    "base" << endl;
        }
        
    int n1;
    };

    class Derived: public Base
    {
    public:
        Derived(): n2(
    0) {}
        
    void fun()
        {
            cout << 
    "derived" << endl;
        }
        
    int n2;
    };

    void test_static_cast()
    {

    }

    void test_dynamic_cast()
    {
        Base *b = 
    new Base();
        Derived *d = 
    new Derived();

        Derived *pd;
        
    // dynamic-cast
        pd = dynamic_cast<Derived *>(b); // pd==null
        if (pd == NULL)
        {
            cout << 
    "first null" << endl; // first null
        }
        
    else
        {
            cout << pd->n2 << endl;
            pd->fun();
        }

        pd = 
    dynamic_cast<Derived *>(d); // pd !=null
        if (pd == NULL)
        {
            cout << 
    "second null" << endl;
        }
        
    else
        {
            cout << pd->n2 << endl; 
    // 0
            pd->fun();          // derived
        }

        
    delete d;
        
    delete b;
    }

    int main()
    {
        
    //test_static_cast();
        test_dynamic_cast();
        
    return 0;
    }
    /*
    first null
    0
    derived
    */

     上述例子,如果改为static_cast,则结果如下

     C++ Code 
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
     
    /*
        version: 1.0
        author: hellogiser
        blog: http://www.cnblogs.com/hellogiser
        date: 2014/9/22
    */


    #include "stdafx.h"
    #include "iostream"
    using namespace std;

    class Base
    {
    public:
        Base(): n1(
    0) {}
        
    virtual void fun()
        {
            cout << 
    "base" << endl;
        }
        
    int n1;
    };

    class Derived: public Base
    {
    public:
        Derived(): n2(
    0) {}
        
    void fun()
        {
            cout << 
    "derived" << endl;
        }
        
    int n2;
    };

    void test_static_cast()
    {
        Base *b = 
    new Base();
        Derived *d = 
    new Derived();

        Derived *pd;
        
    // static-cast
        pd = static_cast<Derived *>(b); // pd!=null
        if (pd == NULL)
        {
            cout << 
    "first null" << endl;
        }
        
    else
        {
            cout << pd->n2 << endl; 
    //      not safe
            pd->fun();              //      not safe
        }

        pd = 
    static_cast<Derived *>(d); // pd !=null
        if (pd == NULL)
        {
            cout << 
    "second null" << endl;
        }
        
    else
        {
            cout << pd->n2 << endl; 
    // 0
            pd->fun();          // derived
        }

        
    delete d;
        
    delete b;
    }

    int main()
    {
        test_static_cast();
        
    return 0;
    }
    /*
    -33686019
    base
    0
    derived
    */

    由此可以看出,对于将基类指针转换为派生类指针的下行转换:

    • static_cast由于不做类型检查,能够正常转换,但是转换后的指针pb指向的是一个不完整的Derived对象,访问Derived对象的成员变量,会出现随机值(-33686019),而访问虚函数fun调用的也是Base的。
    • dynamic_cast做类型检查,知道不能够正常转换,因此返回NULL。

    【const_cast】

    const_cast:用来消除const, volatile, __unaligned属性的转换。

     C++ Code 
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
     
    /*
        version: 1.0
        author: hellogiser
        blog: http://www.cnblogs.com/hellogiser
        date: 2014/9/22
    */


    #include "stdafx.h"
    #include "iostream"
    using namespace std;

    void print (char *str)
    {
        cout << str << 
    ' ';
    }

    void test_const_cast_fun ()
    {
        
    const char *c = "sample text";
        print ( 
    const_cast<char *> (c) ); // const cast
    }

    class CCTest
    {
    public:
        
    void setNumber( int );
        
    void printNumber() const;
    private:
        
    int number;
    };

    void CCTest::setNumber( int num )
    {
        number = num;
    }

    void CCTest::printNumber() const
    {
        cout << 
    "Before: " << number << endl;
        
    const_cast<CCTest *>(this)->number--; // remove const
        cout << "After: " << number << endl;
    }

    void test_const_cast_class()
    {
        CCTest X;
        X.setNumber(
    8);
        X.printNumber();
    }

    int main()
    {
        test_const_cast_fun();
        test_const_cast_class();
        
    return 0;
    }

    /*
    sample text
    Before: 8
    After: 7
    */

    【reinterpret_cast】

    字面意思:重新解释(类型的比特位)。能够在任何类型的指针之间进行转换,也允许将任何整数类型转换为任何指针类型以及反向转换。在所有的转换中最“危险”,一定要慎用。

    来看一个具体的例子:将变量地址转换为一个整数,再由整数转换为对应的指针。

    【代码】

     C++ Code 
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
     
    /*
        version: 1.0
        author: hellogiser
        blog: http://www.cnblogs.com/hellogiser
        date: 2014/9/22
    */


    #include "stdafx.h"
    #include "iostream"
    #include <assert.h>
    using namespace std;

    // address---> integer value
    void test_reinterpret_cast()
    {
        
    int i = 7;
        cout << std::hex << &i << endl;
        
    // pointer to integer
        unsigned int address = reinterpret_cast<unsigned int>(&i); // static_cast is an error
        cout << std::hex << address << ' ';
        
    // integer to pointer
        int *p = reinterpret_cast<int *>(address);
        assert(p == &i);

        
    /*
        int i         7
        int address  ABCD
        int *p       ABCD
        */

    }

    int main()
    {
        test_reinterpret_cast();
        
    return 0;
    }

     在实际中的应用价值:根据地址计算唯一的Hash值。

     C++ Code 
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
     
    /*
        version: 1.0
        author: hellogiser
        blog: http://www.cnblogs.com/hellogiser
        date: 2014/9/22
    */


    #include "stdafx.h"
    #include "iostream"
    using namespace std;

    // Returns a hash code based on an address
    unsigned short Hash( void *p )
    {
        
    unsigned int val = reinterpret_cast<unsigned int>( p );
        
    return ( unsigned short )( val ^ (val >> 16));
    }

    void test_reinterpret_cast()
    {
        
    int a[20];
        
    for ( int i = 0; i < 20; i++ )
            cout << Hash( a + i ) << endl;
    }

    int main()
    {
        test_reinterpret_cast();
        
    return 0;
    }

    /*
    63876
    63992
    63996
    63984
    63988
    63976
    63980
    63968
    63972
    63960
    63964
    63952
    63956
    63944
    63948
    63936
    63940
    64056
    64060
    64048
    */

    【参考】

    http://www.cplusplus.com/doc/tutorial/typecasting/

    http://stackoverflow.com/questions/332030/when-should-static-cast-dynamic-cast-const-cast-and-reinterpret-cast-be-used

    http://blog.csdn.net/callmeback/article/details/4040583

    http://www.cnblogs.com/goodcandle/archive/2009/03/17/1413907.html

    http://en.cppreference.com/w/cpp/language/reinterpret_cast

    个人学习笔记,欢迎拍砖!---by hellogiser

    Author: hellogiser
    Warning: 本文版权归作者和博客园共有,欢迎转载,但请保留此段声明,且在文章页面明显位置给出原文连接。Thanks!
    Me: 如果觉得本文对你有帮助的话,那么【推荐】给大家吧,希望今后能够为大家带来更好的技术文章!敬请【关注】
  • 相关阅读:
    Linq in
    wp7中应用程序清单(WMAppManifest.xml)详细说明
    wp7 给TextBox设置圆角边框
    js 中的闭包
    远程控制PPT软件的帮助
    wp7三种图标大小配置
    在英文版的sqlserver下用LIKE语句不能查询中文
    程序员版《那些年我们一起追过的女孩》(2)
    程序员版《那些年我们一起追过的女孩》(3)
    webbrowser 请求的资源在使用中。 (异常来自 HRESULT:0x800700AA)
  • 原文地址:https://www.cnblogs.com/hellogiser/p/static_cast-dynamic_cast-const_cast-reinterpret_cast.html
Copyright © 2011-2022 走看看