Re: calling virtual function from base class

Discussion in 'C++' started by Phui Hock, Sep 7, 2004.

  1. Phui  Hock

    Phui Hock Guest


    > One thing I think you should realize: If you have a scenario where

    you have
    > a certain function:
    >
    > void EatPoo()
    >
    > And this function is NON-virtual in the base class:
    >
    > class Base
    > {
    > public:
    >
    > void EatPoo()
    > {
    > cout << "Base::EatPoo";
    > }
    > };
    >
    > And then you have a derived class as so:
    >
    > class Derived : public Base
    > {
    > public:
    >
    > virtual void EatPoo()
    > {
    > cout << "Derived::EatPoo";
    > }
    > };
    >
    > That now when you do the following:
    >
    > int main()
    > {
    > Derived k;
    >
    > Base& r = k;
    >
    > r.EatPoo();
    > }
    >
    > It's "Base::EatPoo" that will be called.
    >
    >
    > -JKop


    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
    Phui Hock, Sep 7, 2004
    #1
    1. Advertising

  2. Phui  Hock

    Howard Guest

    "Phui Hock" <> wrote in message
    news:chl3tc$...
    >
    > > One thing I think you should realize: If you have a scenario where

    > you have
    > > a certain function:
    > >
    > > void EatPoo()
    > >
    > > And this function is NON-virtual in the base class:
    > >
    > > class Base
    > > {
    > > public:
    > >
    > > void EatPoo()
    > > {
    > > cout << "Base::EatPoo";
    > > }
    > > };
    > >
    > > And then you have a derived class as so:
    > >
    > > class Derived : public Base
    > > {
    > > public:
    > >
    > > virtual void EatPoo()
    > > {
    > > cout << "Derived::EatPoo";
    > > }
    > > };
    > >
    > > That now when you do the following:
    > >
    > > int main()
    > > {
    > > Derived k;
    > >
    > > Base& r = k;
    > >
    > > r.EatPoo();
    > > }
    > >
    > > It's "Base::EatPoo" that will be called.
    > >
    > >
    > > -JKop

    >
    > 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.


    Which is exactly why it won't call the derived class function! Only virtual
    functions can be overridden by derived classes. Since you're calling a
    non-virtual function on a base class reference, you're only going to see the
    base class function. If you'd called it directly on the object k, then k's
    derived version (which *hides* the base class version now) would be called.

    > ...Does this behavior
    > hold true for all compilers? Or this is just a specific implementation?


    It's a requirement. So it will always happen this way. (Unless your
    compiler is broken :))

    As for how a "vtable" is created or used, there is no requirement in C++
    that such a table exists. The requirement is on how the software behaves,
    not how such behavior is accomplished. Whether such a table exists, and how
    it is filled and used, are defined by the implementor (those who wrote the
    specific compiler).

    > - phui hock
    >


    -Howard

    P.S. to JKop - grow up a little, huh? There's really no need to use such
    adolescent language to make a point!
    Howard, Sep 7, 2004
    #2
    1. Advertising

  3. Phui  Hock

    JKop Guest

    > 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
    JKop, Sep 7, 2004
    #3
  4. Phui  Hock

    JKop Guest

    > P.S. to JKop - grow up a little, huh? There's really no need to use
    > such adolescent language to make a point!


    I know, but it's fun and it makes me smile :-D

    Poo


    -JKop
    JKop, Sep 7, 2004
    #4
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. tomek
    Replies:
    2
    Views:
    676
    Andrey Tarasevich
    Dec 1, 2003
  2. tomek
    Replies:
    3
    Views:
    745
    David Fisher
    Nov 30, 2003
  3. Phui  Hock
    Replies:
    4
    Views:
    463
  4. Andreas Lagemann
    Replies:
    8
    Views:
    482
    Mike Wahler
    Jan 10, 2005
  5. tiwy
    Replies:
    0
    Views:
    440
Loading...

Share This Page