【本文链接】

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. iOS开发小技巧--UIScrollView内部子控件添加约束的注意点

    注意:用UIScrollView时布局子控件的时候,不要相对于UIScrollView来添加约束,这样做不是设置子控件的位置,反而是设置了UIScrollView的contentSize 子控件的尺寸 ...

  2. 【POJ 3176】Cow Bowling

    题 Description The cows don't use actual bowling balls when they go bowling. They each take a number ...

  3. context:exclude-filter 与 context:include-filter 转

    context:exclude-filter 与 context:include-filter 转 1 在主容器中(applicationContext.xml),将Controller的注解打消掉 ...

  4. 【bzoj1037】 ZJOI2008—生日聚会Party

    http://www.lydsy.com/JudgeOnline/problem.php?id=1037 (题目链接) 题意 有n个boy和m个girl排成一排,求使得任意一段的boy个数girl个数 ...

  5. android 常见死机问题--log分析

    http://blog.csdn.net/fangchongbory/article/details/7645815         android 常见死机问题--log分析============ ...

  6. 锋利的jQuery-3--用js给多选的checkbox或者select赋值

    单选的select: <select id="single"> <option>Single</option> <option>Si ...

  7. 转 web项目中的web.xml元素解析

    转 web项目中的web.xml元素解析 发表于1年前(2014-11-26 15:45)   阅读(497) | 评论(0) 16人收藏此文章, 我要收藏 赞0 上海源创会5月15日与你相约[玫瑰里 ...

  8. 可选择Email和用户名登录的代码

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  9. Java-Java中System.arraycopy() 和 Arrays.copyOf()两者之间的区别

    如果我们想拷贝一个数组,我们可能会使用System.arraycopy()或者Arrays.copyof()两种方式.在这里,我们将使用一个比较简单的示例来阐述两者之间的区别. 1.示例代码: Sys ...

  10. vsftpd的安装

    好像linux下的服务的配置和文件分布都差不多, 如httpd, vsftpd, named. 都是: 在/etc/???下面进行配置???.conf, 然后在/var/???放置实际要处理的文件/目 ...