【问题标题】:Why to opt for dynamic_cast in C++ [duplicate]为什么在 C++ 中选择 dynamic_cast [重复]
【发布时间】:2013-04-26 15:55: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;
    }

输出

Gaurav@Gaurav-PC /cygdrive/d/Glaswegian/CPP/Test
$ ./Test
5
10
10
50
50

我的投射方式(行 HERE1 和 HERE2 )和(HERE3 和 HERE4),两者有什么区别?两者都产生相同的输出,那么为什么要选择 dynamic_cast

【问题讨论】:

  • 可能看到这篇文章? stackoverflow.com/questions/28002/…
  • 您可能会发现cplusplus.com/doc/tutorial/typecasting 很有用。它解释了您在 c++ 中的不同转换方式。
  • 转换 HERE3 和 HERE4 没用,编译器可以自动完成:bp = dp;
  • @Muncken 我已经提到了那个教程。我很好奇我的代码中使用的转换类型之间的区别
  • @Gaurav 很棒。如果您还没有,那将是一个很好的开始:)

标签: c++


【解决方案1】:

dynamic_cast 是“安全的”,因为当你在做“坏”的事情时,它要么抛出异常,要么返回 NULL(或者,正如 Nawaz 所说,它无法编译,因为类型非常糟糕,以至于编译器可以看到它出错了)

(Derived *)... 形式的行为类似于 reinterpret_cast&lt;Derived *&gt;(...),这是“不安全的”——它只会将一个指针转换为另一种指针类型,无论这是否产生有意义的结果。如果它表现得“糟糕”,那是你的问题。

你可以这样做:

int x = 4711;

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

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

【讨论】:

  • Mats Petersson .. 所以你的意思是说,它只是类型转换(如果它是排序的(派生 *))而不分析任何结果并且转换总是正确的?
  • "dynamic_cast 是“安全的”,因为它要么抛出异常,要么在你做“坏”的事情时返回 NULL。”, 或者它不编译以开始
  • @GauravK:我稍微修改了我的答案,是的,我是说它几乎会做任何你要求它做的事情,无论这是否是“好”的事情。跨度>
  • @MatsPetersson 知道了int x=450;dp = (Derived *) (&amp;x); cout &lt;&lt; dp-&gt;get_i(); 编译成功并产生随机结果。这是类型转换的 C-Style 对吗?
  • 除了所有这些非常强大的论点之外,Stroustrup 还提出了一个有效的论点,即在代码中很难看到或搜索 C 风格的转换,而使用 C++ 转换很容易做到。跨度>
猜你喜欢
  • 2012-02-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多