1

I've been confused by the converting a pointer to base class object into pointer of derivate class. Please check the following code:

derivate_class *d1 = (derivate_class*)cb;
d1->print();
d1->print1();

The result is:

  • I'm a virtual function in base.
  • I'm a function in derivate class.
  • Can anyone help me explain why d1->print() print "I'm a virtual function in base."?

    #include <iostream>
    using namespace std;
    
    class base
    {
    public:
        virtual void print()
        {
            cout << "I'm a virtual function in base." << endl;
        }
    };
    
    class derivate_class : public  base
    {
    public:
        void print()
        {
            cout << "I rewrite the virtual function in base." << endl;
        }
    
        void print1()
        {   
            cout << "I'm a function in derivate class." << endl;
        }
    };
    
    int main()
    {
        base* b = new base();
        derivate_class *d = new derivate_class();
        b->print();
        d->print1();
        base* cb = b;
        b = d;
        b->print();
        cout << "*********************" << endl;
    
        derivate_class *d1 = (derivate_class*)cb;
        d1->print();
        d1->print1();
    
        system("pause");
        return 0; 
    }
    
    Fihop
    • 3,127
    • 9
    • 42
    • 65
    • You're invoking [UB](http://en.wikipedia.org/wiki/Undefined_behavior) – anything could happen. Switch to `dynamic_cast<>` instead of C-style casts and check for nullptr. – ildjarn Nov 21 '12 at 00:36
    • @ildjarn, thanks so much for your reply. I'm reading source code of STL. In STL of link list, it has some code to convert pointer to base object into pointer of derivate class. So I'm writing the code in the question to test what will happen if converting pointer to base object into pointer of derivate class. My real question is when do we need to convert pointer to base object into pointer of derivate class? I'll post the STL code below. – Fihop Nov 21 '12 at 03:36
    • @ildjarn, I start a new question:http://stackoverflow.com/questions/13486010/why-c-allow-converting-pointer-to-base-object-into-pointer-of-derivate-class – Fihop Nov 21 '12 at 03:43

    2 Answers2

    3

    It's UB, so anything can happen.

    But here's an explanation: d1 doesn't actually point to a derivate_class, but to a base.

    base* b = new base();
    //...
    base* cb = b;
    derivate_class *d1 = (derivate_class*)cb;
    d1->print();
    d1->print1();
    

    The call is resolved dynamically because it's through a pointer and the method is virtual.

    print1 isn't virtual so the call is resolved statically. print however is virtual, so the implementation in the most derived type is called. But the most derived type is actually base in this case.

    Under the hood, the method print is looked for in the virtual function table that the vfptr in cb points to. Since cv is a base, the table will be that of base, which contains the function print with the base::print implementation. That's why that's the function getting called.

    Luchian Grigore
    • 253,575
    • 64
    • 457
    • 625
    • thanks so much for your reply. I'm reading source code of STL. In STL of link list, it has some code to convert pointer to base object into pointer of derivate class. So I'm writing the code in the question to test what will happen if converting pointer to base object into pointer of derivate class. My real question is when do we need to convert pointer to base object into pointer of derivate class? I'll post the STL code below. – Fihop Nov 21 '12 at 03:35
    • I start a new question:http://stackoverflow.com/questions/13486010/why-c-allow-converting-pointer-to-base-object-into-pointer-of-derivate-class – Fihop Nov 21 '12 at 03:44
    0

    d1 is a derivate_class pointer but the data it's actually pointing to (cb) is of type base. Since print() is virtual, the call is resolved dynamically and so it will find base's implementation in the virtual function table instead of derivate_class's.

    Foggzie
    • 9,691
    • 1
    • 31
    • 48