简体   繁体   中英

runtime polymorphism and dynamic_cast need clarification

Might answered some where else, but could not found right phrase to ask

so hear it goes.

I have base class A , with child B and C ; (completely for training purpose)

#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; } 
};

so, in my main I have declared base pointer A* bptr; later child's B and C also declared.

later bPtr pointed to B and called print function works as expected; later bPtr pointed to C and called print function works as expected;

hear is code, no problems hear.

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;

}

hear is my dilemma, I may understand wrong; now what I thought all these days, dynamic_cast also does exactly above; but things are different OR I am doing something wrong.

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;
    }

}  

so hear is my question is dynamic_cast good for and only places like if statement to determine the existence of inheritance between base and child's or safe cast between base and child's?

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

This behaviour has nothing to do with dynamic_cast.

The behaviour of a virtual call will always depend on the actual runtime type of the value. In your second example, the only thing actually constructed is a C , so all calls will resolve to C, whether you call it an A: A * a = bPtr or a B: B * b = bPtr , it will resolve to C::print() because the statement new C constructs the actual value as a C.

Dynamic_cast is just going to cast the value given to the type specific, if it is (a subtype of) that type, or otherwise return nullptr . So dynamically casting a B * to C * will fail and return nullptr , but in your case you are casting C * to one of its base types, which will always succeed and never change the value itself.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM