Anurag Sharma
Anurag Sharma

Reputation: 5039

What happens when base class object calls derived class function (which is non virtual)

Pardon me if the question found silly to you. I am a newbie to c++ and I was studying rum time polymorphism. I want to know what happens when base class object calls derived class function (which is non virtual). for example look at the code

class base {
    public:
        virtual void vfunc() {cout << "This is base's vfunc().\n";}
};

class derived1 : public base {
    public:
        void vfunc() {cout << "This is derived1's vfunc().\n";}
};

int main()
{
    base *p, b;
    derived1 d1;

    p = &b;
    p->vfunc();

    p = &d1;
    p->vfunc();

    return 0;
}

I got the desired ouput, I then removed the virtual keyword from the base class and when I ran the program the output is

This is base's vfunc().
This is base's vfunc().

I will be very thankful if some one explain what happened (in terms of pointer manipulation) in both of the cases

Thanks

Upvotes: 2

Views: 1042

Answers (2)

Lazer
Lazer

Reputation: 94820

In the virtual case, at runtime, p->vfunc() tells p to go to the class definition of the class (whatever part of it is in memory) that the pointee belongs to, and read its vtable (or some similar alternate implementation) to figure out which function to call.

Suppose the vtables look like below:

base's vtable:

----------------
vfunc | 0x2048
---------------- 

derived1's vtable:

----------------
vfunc | 0x2096
---------------- 

Then base version or derived version of vfunc is called depending on where vtables point.

In non-virtual case, none of this happens, and the function to call is set in stone by the compiler at compile time. During compile time, all the compiler can figure out is that p is of type 'pointer to base' and changes all the p->vfunc() calls to point to address 0x2048.

Upvotes: 2

Borgleader
Borgleader

Reputation: 15916

What's going on here is that there are two vtables, one for base and one for derived. In base's vtable you have one entry for vfunc(), and in derived's vtable there is also one entry, the trick is when derived took it's parent's vtable it looked to see if it was overriding any of it's parent's virtual methods and it is. So it replaced what was there so that it now points to it's own version.

In other words, when you call vfunc() through an instance of type base, you check the base vtable which contains a pointer to bases's vfunc(). When you call it through an instance of derived, you find the pointer to derived's vfunc().

If you remove the virtual keyword, the compiler is no longer looking for a virtual function so instead of basing himself on the run time type of the object, it's basing itself on it's static/compile time type.

In other words, without the virtual keyword the compiler looks at the type of the pointer which is base, so it calls the base version, every time.

Upvotes: 1

Related Questions