关于c ++:dynamic_cast的好处/用途是什么?

What is the benefit/use of dynamic_cast?

本问题已经有最佳答案,请猛点这里访问。
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
class Base
{
        public:
        virtual void print (){cout<<"Base"<<endl;}
};

class Derived :public Base
{
        public:
        virtual void print (){cout<<"Derived"<<endl;}
};

int main(){
        Base *ptrb1=new Base();
        //it will print Base
        ptrb1->print();

        Base *ptrb2=new Derived();
        // it will print Derived
        ptrb2->print();

        Derived *ptrd=NULL;
        //what is the difference between 2ways?
        //what is the benefit of useing dynamic_cast?
        ptrd=dynamic_cast<Derived*>(ptrb2);
        ptrd->print();
}

如果我们可以通过添加虚函数使基类看到派生类的成员,并使基从派生类向obj指示,那么动态类型转换的好处(或两者之间的区别)是什么?


如果不使用强制转换,则非虚拟成员函数将调用基方法。下面的代码显示了虚函数和非虚函数之间的区别,以及动态强制转换之后会发生什么。

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
class Base
{
public:
    void print2() {
        cout <<"Base" << endl;
    }
    virtual void print() {
        cout <<"Base" << endl;
    }
};

class Derived : public Base
{
public:
    void print2() {
        cout <<"Derived" << endl;
    }
    virtual void print() {
        cout <<"Derived" << endl;
    }
};

int main()
{
    Base* ptrb1 = new Base();
    //it will print Base
    ptrb1->print();
    ptrb1->print2();

    Base* ptrb2 = new Derived();
    // it will print Derived
    ptrb2->print();
    ptrb2->print2();

    Derived* ptrd = NULL;
    //what is the difference between 2ways?
    //what is the benefit of useing dynamic_cast?
    ptrd = dynamic_cast<Derived*>( ptrb2 );
    ptrd->print();
    ptrd->print2();
}

如果您要使用static_cast(正如您在重新转换指针时可能倾向于认为可以这样做),那么仍然从基派生的另一个类将被错误地转换。dynamic_cast将显示铸型不可能,而返回nullptr


dynamic_cast提供了一个基于运行时类型信息的子类检查,回答了以下问题:

is the this base class object of a specific derived type?

如果答案是"是"(强制转换成功),那么我们可以使用对象作为其派生类型,否则不能。

如果没有运行时类型信息和EDCOX1(1),C++程序员就不得不把它们自己的特定类型的测试结合在一起做同样的事情。

为什么您有时需要一个显式类型检查,是因为需要执行一些特定于子类型的小操作,并且您不希望只为这个小东西引入一个虚拟方法的繁琐形式。

其他类型转换(如static_castdynamic_cast的不同之处在于,它们不进行运行时类型检查,也不会失败:它们在强制进行不合理的转换时会产生虚假结果,而不是失败。


尽可能使用这样的虚拟函数。

在下列情况下使用dynamic_cast

  • 您无法找到使用虚拟函数的方法,或者
  • 函数是如此特定于派生类,在基接口中放置任何关于它的内容都没有意义,或者
  • 你需要找出你的基指针是否真的是一种特殊的派生类型,而不是仅仅要求它去做或者得到一些东西。