【本文链接】

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
, B, C };
;
;
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() {}
    int n1;
};

class Derived: public Base
{
public:
    Derived(): n2() {}
    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();
    ;
}

【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() {}
    virtual void fun()
    {
        cout << "base" << endl;
    }
    int n1;
};

class Derived: public Base
{
public:
    Derived(): n2() {}
    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();
    ;
}
/*
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() {}
    virtual void fun()
    {
        cout << "base" << endl;
    }
    int n1;
};

class Derived: public Base
{
public:
    Derived(): n2() {}
    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();
    ;
}
/*
-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 << '\n';
}

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();
    X.printNumber();
}

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

/*
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()
{
    ;
    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 << '\n';
    // 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();
    ;
}

在实际中的应用价值:根据地址计算唯一的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 );
    ));
}

void test_reinterpret_cast()
{
    ];
    ; i++ )
        cout << Hash( a + i ) << endl;
}

int main()
{
    test_reinterpret_cast();
    ;
}

/*
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

static_cast dynamic_cast const_cast reinterpret_cast总结对比的更多相关文章

  1. static_cast, dynamic_cast, const_cast

    http://www.cnblogs.com/chio/archive/2007/07/18/822389.html 首先回顾一下C++类型转换: C++类型转换分为:隐式类型转换和显式类型转换 第1 ...

  2. static_cast, dynamic_cast, const_cast探讨

    转自:http://www.cnblogs.com/chio/archive/2007/07/18/822389.html 首先回顾一下C++类型转换: C++类型转换分为:隐式类型转换和显式类型转换 ...

  3. 【C++专题】static_cast, dynamic_cast, const_cast探讨

    首先回顾一下C++类型转换: C++类型转换分为:隐式类型转换和显式类型转换 第1部分. 隐式类型转换 又称为“标准转换”,包括以下几种情况:1) 算术转换(Arithmetic conversion ...

  4. C++之static_cast, dynamic_cast, const_cast

    转自:http://www.cnblogs.com/chio/archive/2007/07/18/822389.html 首先回顾一下C++类型转换: C++类型转换分为:隐式类型转换和显式类型转换 ...

  5. static_cast, dynamic_cast, const_cast 类型转换如何使用?

    static_cast 用法:static_cast < type-id > ( expression ) 说明:该运算符把expression转换为type-id类型,但没有运行时类型检 ...

  6. static_cast, dynamic_cast, const_cast 三种类型转化的区别

    强制转化四种类型可能很多人都常常忽略就象我一样,但是有时还是比较有用的.不了解的建议看看,一些机制我也不是十分了解,只是将一些用法写出来让大家看看.                           ...

  7. c++ 数据类型转换: static_cast dynamic_cast reinterpret_cast const_cast

    c++ 数据类型转换: static_cast dynamic_cast reinterpret_cast const_cast  [版权声明]转载请注明出处 http://www.cnblogs.c ...

  8. static_cast、dynamic_cast、reinterpret_cast、const_cast以及C强制类型转换的区别

    static_cast 1. 基础类型之间互转.如:float转成int.int转成unsigned int等 2. 指针与void*之间互转.如:float*转成void*.CBase*转成void ...

  9. C++雾中风景11:厘清C++类型转换(static_cast,dynamic_cast,reinterpret_cast,const_cast)

    C++是一门弱类型的语言,提供了许多复杂和灵巧类型转换的方式.笔者之前写的Python与Go都是强类型的语言,对这种弱类型的设计实在是接受无力啊~~ ( 生活所迫,工作还得写C++啊~~)C++语言提 ...

随机推荐

  1. JS模式:简单的图书馆享元模式

    <!DOCTYPE html> <html> <head> <title></title> </head> <body&g ...

  2. 【UVA 1451】Average

    题 题意 求长度为n的01串中1占总长(大于L)的比例最大的一个子串起点和终点. 分析 前缀和s[i]保存前i个数有几个1,[j+1,i] 这段区间1的比例就是(s[i]-s[j])/(i-j),于是 ...

  3. Dinic问题

    问题:As more and more computers are equipped with dual core CPU, SetagLilb, the Chief Technology Offic ...

  4. BZOJ4590 自动刷题机

    Description 曾经发明了信号增幅仪的发明家SHTSC又公开了他的新发明:自动刷题机--一种可以自动AC题目的神秘装置.自动 刷题机刷题的方式非常简单:首先会瞬间得出题目的正确做法,然后开始写 ...

  5. 通过HTTP协议实现多线程下载

    1. 基本原理,每条线程从文件不同的位置开始下载,最后合并出完整的数据. 2. 使用多线程下载的好处     下载速度快.为什么呢?很好理解,以往我是一条线程在服务器上下载.也就是说,对应在服务器上, ...

  6. bootstrap学习总结-06 按钮

    一按钮的基本样式 Bootstrap提供一组标准的按钮配色和大小调整方案,只需要简单的应用的按钮类即可.BootStrap3提供了按钮的标准样式如图. <!DOCTYPE html> &l ...

  7. 项目总结—jQuery EasyUI- DataGrid使用

    http://blog.csdn.net/zwk626542417/article/details/18839349 概要 jQuery EasyUI是一个基于jquery的集成了各种用户界面的框架, ...

  8. 【js】JSON.stringify 语法实例讲解

    语法:  JSON.stringify(value [, replacer] [, space]) value:是必选字段.就是你输入的对象,比如数组,类等. replacer:这个是可选的.它又分为 ...

  9. IbatisNet的介绍和使用

    http://dragonsuc.cnblogs.com/archive/2006/07/04/ibatisnet.html IbatisNet的介绍和使用http://files.cnblogs.c ...

  10. JavaScript input file上传前获取文件名、文件类型、文件大小等信息

    document.getElementById("productImgInput").files[0].type document.getElementById("pro ...