为什么选择C ++中的dynamic_cast


Why to opt for dynamic_cast in C++

本问题已经有最佳答案,请猛点这里访问。

考虑以下代码:

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
#include <iostream>

using namespace std;

class Base{
    int i;
    public:
    virtual bool baseTrue() {return true;}
    Base(int i) {this->i=i;}
    int get_i() {return i;}
    };

class Derived : public Base{
    int j;
    public:
    Derived(int i,int j) : Base(i) {this->j=j;}
    int get_j() {return j;}
    };

int main()
{
    Base *bp;
    Derived *pd,DOb(5,10);

    bp = &DOb;

    //We are trying to cast base class pointer to derived class pointer
    cout << bp->get_i() << endl;
    cout << ((Derived *)bp)->get_j() << endl;**//HERE1**

    pd=dynamic_cast<Derived*> (bp); **//HERE2**
    // If base class is not polymorphic
    //throw error
    //error: cannot dynamic_cast `bp' (of type `class Base*') to
    //type `class Derived*' (source type is not polymorphic)

    cout << pd->get_j() << endl;**//HERE2**

    //Now we try to cast derived Class Pointer to base Class Pointer

    Base *pb;
    Derived *dp,Dbo(50,100);
    dp = &Dbo;


    cout << ((Base *)dp)->get_i() << endl;**//HERE3**
    //cout << ((Base *)dp)->get_j() << endl;
    //throws error Test.cpp:42: error: 'class Base' has no member named 'get_j'

    pb =  dynamic_cast<Base * > (dp); **//HERE4**
    cout << pb->get_i() << endl; **//HERE4**
    //cout << pb->get_j() << endl;
    //throws error Test.cpp:47: error: 'class Base' has no member named 'get_j'


    return 0;
    }

输出

1
2
3
4
5
6
7
Gaurav@Gaurav-PC /cygdrive/d/Glaswegian/CPP/Test
$ ./Test
5
10
10
50
50

我的演员阵容(这里1行和这里2行)和(这里3行和这里4行),这两者有什么区别?两者产生相同的输出,所以为什么要进行动态铸造?


dynamic_cast是"安全的",因为它要么抛出异常,要么在执行"坏"操作时返回空值(或者,正如nawaz所说,它不编译,因为类型足够糟糕,编译器会看到它出错)。

(Derived *)...形式的作用类似于reinterpret_cast(...),这是"不安全的"—它将简单地将一个指针转换为另一个指针类型,无论是否产生有意义的结果。如果你表现得"糟糕",那就是你的问题。

您可以这样做:

1
2
3
4
int x = 4711;

Derived *dp = (Derived *)x;
cout << dp->get_j();

编译器可能会抱怨整数的大小,但否则,它将编译代码。它很可能根本不会运行,但如果运行成功,结果可能就没有什么"有用"了。