`dynamic_cast` from Base to Derived

Alcott picture Alcott · Apr 2, 2012 · Viewed 9.8k times · Source

Yes, I know that downcast using dynamic_cast can't compile if the Base is not polymorphic, but my problem is not about this.

class Base {
    public:
        virtual void bar()
        {
            cout << "bar\n";
        }
};

class Derived: public Base {
    public:
        void foo()
        {
            cout << "foo\n";
        }
};

int main()
{
    Base *pb;
    Derived *pd;

    pb = new Derived;  //Base* points to a Derived object
    pd = dynamic_cast<Derived*>(pb); 
    pd->foo();  //outputs foo

    pb = new Base;  //Base* points to a Base object
    pd = dynamic_cast<Derived*>(pb);  
    pd->foo();  //outputs foo, too. Why?
}

I thought when pb = new Derived;, pb actually points to a Derived object lies in heap. After pd = dynamic_cast<Derived*>(pb);, pd also points to that Derived object, so pd->foo() should be OK.

But when pb = new Base;, what pb points to is a Base object in heap, then after pd = dynamic_cast<Derived*>(pb);, how could pd->foo() works? Did dynamic_cast turn the Base object in heap into a Derived object?

Answer

Rohan Prabhu picture Rohan Prabhu · Apr 2, 2012

In C++, each instance of a class has its own version of datatypes, but all classes share the same function in memory (other than for inline functions). In your case, when you say something like:

pd->foo();

You are essentially calling Derived::foo, which is a function in memory and the compiler knows where it is. The thing is, it is not dependent on pd at all. However, if you had something like this:

class Derived : public Base {
    private:
        int a;

    public:
        Derived() { a = 100; }

        void foo() {
            std::cout<<a<<std::endl;
        }
 };

Then, pd->foo() will cause a Segmentation fault. Here, your dynamic cast has failed and when Derived::foo is called, it is passed 0 as the this object. It was fine in the previous case, as the this object was never used. However, in the second case, it is used and hence, causes a Segmentation fault.