【本文链接】

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. .net架构设计读书笔记--第三章 第9节 域模型实现(ImplementingDomain Model)

        我们长时间争论什么方案是实现域业务领域层架构的最佳方法.最后,我们用一个在线商店案例来说明,其中忽略了许多之前遇到的一些场景.在线商店对很多人来说更容易理解. 一.在线商店项目简介 1. 用例 ...

  2. Spring-事物-不依赖应用服务器的开源JTA事物实现

    不依赖应用服务器的开源JTA事物实现JOTM和Atomikos Transactions JOTM 即基于Java开放事务管理器(Java Open Transaction Manager),实现JT ...

  3. jquery插件库

    jQuery由美国人John Resig创建,至今已吸引了来自世界各地的众多javascript高手加入其team. jQuery是继prototype之后又一个优秀的Javascrīpt框架.其经典 ...

  4. 【CodeForces 606A】A -特别水的题1-Magic Spheres

    http://acm.hust.edu.cn/vjudge/contest/view.action?cid=102271#problem/A Description Carl is a beginne ...

  5. ActiveRecord中andFilterWhere使用

    查询数据库时 $model; if(!empty($name)) { $model->andWhere(['name'=>$name]); } 可以用andFilterWhere,自动的把 ...

  6. 学习笔记-KMP算法

    按照学习计划和TimeMachine学长的推荐,学习了一下KMP算法. 昨晚晚自习下课前粗略的看了看,发现根本理解不了高端的next数组啊有木有,不过好在在今天系统的学习了之后感觉是有很大提升的了,起 ...

  7. hdu 3068 最长回文子串 TLE

    后缀数组+RMQ是O(nlogn)的,会TLE..... 标准解法好像是马拉车,O(n).... #include "algorithm" #include "cstdi ...

  8. Bzoj3943 [Usaco2015 Feb]SuperBull

    3943: [Usaco2015 Feb]SuperBull Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 300  Solved: 185 Desc ...

  9. iOS应用开发最佳实践系列一:编写高质量的Objective-C代码

          本文由海水的味道编译整理,转载请注明译者和出处,请勿用于商业用途! 点标记语法 属性和幂等方法(多次调用和一次调用返回的结果相同)使用点标记语法访问,其他的情况使用方括号标记语法. 良好的 ...

  10. [Angularjs]视图和路由(二)

    写在前面 上篇文章主要介绍了视图和路由的基本概念,并在文章最后举了一个简单的使用案例.这篇文章将继续学习路由的配置,及相关参数的说明. 系列文章 [Angularjs]ng-select和ng-opt ...