c++ - 在实践中,从父级到子级的 dynamic_cast 何时有用?这总是不好的做法吗?

标签 c++ polymorphism rtti dynamic-cast

在实践中,从父级到子级的 dynamic_cast 何时有用?
这总是不好的做法吗?
这不是以下内容的重复:
C++ Polymorphism: from parent class to child
Run-time type information in C++
首先,让我们从一个代码示例开始,然后得出一些结论。

#include<iostream> 
using namespace std; 
class B { public: virtual void fun() {cout<<"!class B!\n";} }; 
class D: public B { public: void fun() {cout<<"!class D!\n";} }; 

int main() 
{ 
/////////   1. Dynamic initialization parent from child

B *bAux = new D; 
D *d = dynamic_cast<D*>(bAux); 
cout<<"1.1. for d is "; d->fun();   //class D

B *b = dynamic_cast<B*>(d);
cout<<"1.2. for b is "; b->fun();   //class D

/////////   2. Dynamic initialization child from parent

//D *dAux4 = new B;  //invalid conversion from ‘B*’ to ‘D*’

/////////   3. Casting the parent to child

B *bAux2 = new B;
cout<<"3.1. for bAux2 is "; bAux2->fun();   //class B

D *d2 = dynamic_cast<D*>(bAux2); 
if (d2 != NULL){ cout<<"3.2. for d2 is "; d2->fun(); }  //cannot cast parent to child
else cout<<"3.2. cannot cast B* to D* \n";

/////////   4. Casting the child to parent

D *dAux3 = new D;
cout<<"4.1. for dAux3 is "; dAux3->fun();   //class D

B *b3 = dynamic_cast<B*>(dAux3); 
cout<<"4.2. for b3 is "; b3->fun();   //class D

getchar(); 
return 0; 
} 
其次,让我们得出结论。
输出是:
1.1. for d is !class D!                                                                                                                      
1.2. for b is !class D!                                                                                                                      
3.1. for bAux2 is !class B!                                                                                                                  
3.2. cannot cast B* to D*                                                                                                                    
4.1. for dAux3 is !class D!                                                                                                                  
4.2. for b3 is !class D!
但是对于案例 3,我们实际上尝试从 B* 动态转换为 D*(如前所述,这是不可能的)。我想知道这在哪些情况下有用?您可以打破强制类型转换(类似地,在静态类型检查的情况下,有一个众所周知的问题:既然熊是动物,那么一组熊不应该是一组动物吗?不,因为然后你可以在集合中插入一只狼并在熊中拥有一只狼)。
那么,问题是,在哪种情况下,从父级到子级的动态转换有用?这是一个不好的做法吗?
编辑:
经过讨论,一个特例:
/////////   5. Try to cast the parent initialized from a child to another child

B *bAux = new D; 
F *f = dynamic_cast<F*>(bAux); 
if(f == NULL)
    cout<<"5.1. Cannot cast the parent initialized from a child to another child \n";// f->fun();   //segmentation fault

B *b = dynamic_cast<B*>(f);
if(b == NULL)
    cout<<"5.2. Cannot cast the NULL pointer back to parent \n"; //b->fun();   //segmentation fault

最佳答案

dynamic_cast 对于您想要获取派生对象接口(interface)的情况很有用:
如果派生中有 f() 而基中没有 f() 函数,则不能通过 B* 调用 f()。但
您可以 dynamic_cast 到 D* 并调用 f() (如果 B* 指向 D 对象)。 (记住 dynamic_cast 是针对多态类型的)
考虑以下代码:

class B {
public:
    virtual void g()
    {
        std::cout << "Base::g()\n";
    }
};
class D : public B
{
public:
    void f()
    {
        std::cout << "f()\n";
    }
    void g()
    {
        std::cout << "Derived::g()\n";
    }
};
int main()
{
    B* p = new D;
    //p->f(); // class B has no member f
    D* pd = dynamic_cast<D*>(p);
    pd->f(); // ok f() will be called

    return 0;
}

关于c++ - 在实践中,从父级到子级的 dynamic_cast 何时有用?这总是不好的做法吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65670832/

相关文章:

java - 为什么我的对象不需要调用 .toString 方法?

delphi - 如何使用 RTTI 获取数组的元素类型

c++ - 链表 - 覆盖数据

java - 在调用父类和子类中可用的方法时,在多态性中选择了哪个方法?

c++ - 在 C++ 中,哪种方法更好地创建固定长度的数组?

C++:访问祖 parent 方法

c++ - 在 C++ 中查找未知对象的类型

delphi - Delphi 属性真实世界示例在哪里?

c++ - 从外部函数访问外部结构属性

c++ - 为什么 Visual Studio 不在 self 赋值时发出警告 (int foo = foo;)