【本文链接】

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. 利用HTML5的Video进行视频截图并保存到本地

    <!doctype html> <html> <head> <meta charset="utf-8"> <title> ...

  2. Java基础--重写(Overriding,覆盖)-重载(Overloading)

    多态性: Java的方法重载,就是在类中可以创建多个方法,它们具有相同的名字,但具有不同的参数和不同的定义.调用方法时通过传递给它们的不同参数个数和参数类型来决定具体使用哪个方法 Java的方法重写, ...

  3. BRIEF算法

    本文结构 为了看懂ORB特征提取算法,来看了BRIEF算法的原文,并查看了OpenCV中BRIEF的相关实现,来验证论文的解读正确与否. BRIEF论文解读 摘要 用二进制串描述局部特征,好处有二:一 ...

  4. bzoj3555 企鹅QQ

    3555: [Ctsc2014]企鹅QQ Time Limit: 20 Sec  Memory Limit: 256 MBSubmit: 1640  Solved: 613 Description P ...

  5. 在excel批量更改单元格类型后的批量刷新显示

    把E的东西变成完整显示 解决办法: 选中所需要更改的整列数据------>菜单栏的数据选项------>分列

  6. git分支与版本管理、版本回退、冲突解决记录

    一.基础使用 1.初始化本地仓库 git init 2.关联远程仓库 git remote add origin git@github.com:用户名/仓库名.git 3.添加远程仓库文件到本地 gi ...

  7. Mysql 学习-索引的设计原则

    索引的设计不合理或者缺少索引都会对数据库和应用程序的性能造成障碍.高效的索引对获的良好性能非常重要.设计索引是,应该考虑一下准则: (1)索引并非语讹夺越好,若一个表中有大量索引,不仅占用磁盘空间,而 ...

  8. nginx 启动/停止/重启 BAT

    cls @ECHO OFF SET NGINX_PATH=D: SET NGINX_DIR=D:\Hack\nginx\color 0a TITLE Nginx 管理程序 Power By AntsG ...

  9. 常用webshell提权方法总结

    pcAnywhere提权:1.利用pcAnywhere提权,前提条件是pcAnywhere默认安装到默认路径,以及它的目录安全权限有users权限,如果管理员删除了users和power users用 ...

  10. 行为Behavior的使用

    原文地址:http://www.it610.com/article/4918541.htm 行为就是继承yii\base\behavior,可以绑定到任意yii\base\compent实例上,然后这 ...