首页 > 解决方案 > 运行时多态性和 dynamic_cast 需要澄清

问题描述

可能会在其他地方回答一些问题,但找不到正确的短语来提问

所以听到它去。

我有基类A,有孩子BC;(完全用于培训目的)

#include <iostream>

class A 
{ 
    public: 
        virtual void print () { std::cout<< "A::print()" << std::endl; } 
}; 

class B: public A 
{ 
    public: 
        void print () { std::cout<< "B::print()" << std::endl; } 
}; 

class C : public B 
{ 
    public: 
        void print () { std::cout<< "C::print()" << std::endl; } 
};

所以,在我的主要声明中,我已经声明了基指针A*bptr;后来孩子的BC宣布了。

后来 bPtr 指向B并调用print的函数按预期工作;后来 bPtr 指向C并调用print的函数按预期工作;

听到是代码,没有问题听到。

int main()  
{
    A* bPtr;

    B b;
    C c;

    bPtr = &b;
    bPtr->print(); // prints B::print() - as expected;

    bPtr = &c;
    bPtr->print(); // prints C::print() - as expected;

}

听到是我的困境,我可能理解错了;现在我这些天的想法,dynamic_cast也完全在上面;但情况有所不同,或者我做错了什么。

int main()
{

    A* bPtr = new C;

    bPtr = dynamic_cast<B*>( bPtr );

    bPtr->print(); // prints C::print() - expected B::print()

    /*
        I know above can be correct with explicit call
    */

    (dynamic_cast<B*>( bPtr ))->B::print(); // B::print


    bPtr = dynamic_cast<C*>( bPtr );

    bPtr->print(); // prints C::print()

    return 0; 


    if ( B* b = dynamic_cast<B*>( bPtr ))
    {
        b->print(); // still calls C::print() anyway;
    }

}  

所以听到我的问题是dynamic_cast有好处的,并且只有像if声明这样的地方才能确定基础和孩子之间是否存在继承或基础和孩子之间是否存在安全转换?

if ( B* b = dynamic_cast<B*>( bPtr ))
{
        b->print(); // still calls C::print() anyway;
}

标签: c++polymorphismdynamic-cast

解决方案


此行为与 dynamic_cast 无关。

虚拟调用的行为将始终取决于值的实际运行时类型。在您的第二个示例中,唯一实际构造的是 a C,因此所有调用都将解析为 C,无论您将其称为 A:A * a = bPtr还是 B: B * b = bPtr,它都会解析为 C::print() ,因为该语句new C构造了实际值作为一个 C。

Dynamic_cast 只是将给定的值转换为特定类型,如果它是该类型的(子类型),否则返回nullptr。因此,动态转换 a B *toC *将失败并返回nullptr,但在您的情况下,您将转换C *为它的一种基本类型,它将始终成功并且永远不会更改值本身。


推荐阅读