Re: calling virtual function from base class

From: JKop (NULL_at_NULL.NULL)
Date: 09/07/04


Date: Tue, 07 Sep 2004 21:04:29 GMT


> Hi,
> How is that possible? To my understanding, when a class contains a
> virtual function such as Derived, compiler will insert a vtable for
> that class and fill the vtable with the address of virtual functions of
> Derived or Base. But Base's EatPoo() is not virtual. Does this behavior
> hold true for all compilers? Or this is just a specific implementation?
> - phui hock

Okay first thing's first. We start off with:

class Base
{
public:

            void EatPoo()
            {
                        cout << "Base::EatPoo";
            }
};

int main()
{
            Base blah;

            blah.EatPoo();
}

"Base" is in NO way polymorphic, which means that it contains no virtual
functions. In particular, the function "EatPoo" is not virtual. As such,
when you make a call to "EatPoo", when the compiler is compiling the code it
already knows exactly what function is being called, there's no "look-up".
The same holds true for a reference:

int main()
{
            Base blah;

            Base& cow = blah;

            cow.EatPoo();
}

There's no "look-up" at all whatsoever in the above, "Base" is just a run-
of-the-mill non-polymorphic class. Now that's that.

Time goes by and some-one writes the following class:

class Derived : public Base
{
public:

            virtual void EatPoo()
            {
                        cout << "Derived::EatPoo";
            }
};

int main()
{
            Derived monkey;

            monkey.EatPoo();
}

This time, when you call "EatPoo" (in the context of a "Derived", by which I
mean that it's upon an object of type "Derived" that you're calling the
member function "EatPoo"), it's Derived::Poo that's called. As such, when
you call the function "EatPoo" in the context of a "Derived", then there IS
a "look-up".

Which brings me to:

int main()
{
            Derived cheese;

            cheese.EatPoo();
            //The above will call Derived::EatPoo

            Base& chalk = cheese;

            chalk.EatPoo();
            //The above will call Base::EatPoo
}

Do you understand why it calls Base::EatPoo in the above? "Base" doesn't
need to know that "Derived" even exists. Imagine that "Base", a NON-
polymorphic class, was written 5 years ago and only now 2 days ago has some-
one written a polymorphic class that inherits from Base. If you do stuff in
the context of a "Base" object, as I have above by defining the reference
"chalk", then you're working with a non-polymorphic object; in particular,
the function "EatPoo" is non-virtual, there will be no "look-up", the
compiler knows at compile-time exactly what function it's calling. But when
you work with it in the context of a "Derived", you're working with a
virtual function, and as such, when you call it, a "look-up" IS performed.

So, in summation, the following code will behave identically on all
implementations. The first output will be "Derived::EatPoo", the second will
be "Base::EatPoo":

#include <iostream>

class Base
{
public:

            void EatPoo()
            {
                        std::cout << "Base::EatPoo";
            }
};

class Derived : public Base
{
public:

            virtual void EatPoo()
            {
                        std::cout << "Derived::EatPoo";
            }
};

int main()
{
            Derived blah;

            blah.EatPoo();

            Base& monkey = blah;

            std::cout << '\n'; //New line

            monkey.EatPoo();
}

Hope that helps,

-JKop



Relevant Pages

  • Re: Interview questions
    ... How did your compiler know where to get the entry point for Hello? ... > without calling a wrapper function. ... *without* any public definition of the virtual function table. ... The programmer is playing the role of the compiler. ...
    (comp.lang.cpp)
  • Re: When is a static data member defined?
    ... >> After examining the object files emitted by the compiler for various ... > to implement a language in general. ... > language definition: virtual function mechanism implementation. ... then our deductions constitute mathematics. ...
    (comp.lang.cpp)
  • Re: Why I cannt use dynamic_cast to convert from a non-polymorphic class
    ... Why the compiler insist on requiring the the ... must be of a class that has at least one virtual function. ... pointer to RTTI data structures to a class's vtbl, ... the layout of B objects can have extra data to support polymorphism, ...
    (microsoft.public.vc.language)
  • Re: Interview questions
    ... And here's the assembly code my compiler generates for Test: ... > in the virtual function table. ... layout from the class definition, ... Therefore, things like vtables and virtual calls, which a C++ ...
    (comp.lang.cpp)
  • Re: It Pays to Enrich Your C Skills
    ... Check if you can score a perfect 10 (without using a compiler). ... int main{ ... struct bitfield { ... out if it is a negative integer constant or a constant expression ...
    (comp.lang.c.moderated)