CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 15 of 15
  1. #1
    Join Date
    May 2008
    Posts
    6

    vtable question: why its own method is called rather than the parent's one?

    class B derives from class A,
    A has two virtual methods: f1( ) and f2( ). In A::f1( ), it call f2( ).
    B override both virtual methods. In B::f1( ), it call A::f1( ). The question is: why B::f2( ) is called rather than A::f2( ).

    Thanks!


    Code:
    #include <stdio.h>
    
    class A
    {
        public: virtual void f1()
        {
            f2();
        }
    
        public: virtual void f2()
        {
            printf("A.f2()\n");
        }
    };
    
    class B : A
    {
        public: virtual  void f1()
        {
            A::f1();
        }
        public: virtual void f2()
        {
            printf("B.f2()\n");
        }
    };
    
    int main(int argc, char** argv)
    {
        B * b = new B();
        b->f1();
        delete b;
    }
    The output is:
    >> B.f2()
    Last edited by haiyeong; May 30th, 2008 at 08:19 PM. Reason: typo

  2. #2
    Join Date
    Dec 2006
    Posts
    166

    Re: vtable question: why its own method is called rather than the parent's one?

    It looks reasonable. What did you expect it to do? The method "f2" is virtual, so it calls the "f2" method of the actual type of the object, which is B.

  3. #3
    Lindley is offline Elite Member Power Poster
    Join Date
    Oct 2007
    Location
    Seattle, WA
    Posts
    10,895

    Re: vtable question: why its own method is called rather than the parent's one?

    Since you're using a B* anyway, of course it's going to call B's method. If you were using an A* you'd get the same behavior, but it would at least make sense to be surprised in that case.

    I suspect you've got a backwards notion of how inheritance works......children can override parents, not the other way around.

  4. #4
    Join Date
    May 2008
    Posts
    6

    Re: vtable question: why its own method is called rather than the parent's one?

    what I was thinking is how the execution pointer been moved back from A::f1( ) back to B.

    vtable for A:
    0: pointer to A::f1
    4: pointer to A::f2

    vtable for B:
    0: pointer to B::f1
    4: pointer to B::f2

    The execution process would be:
    1. call b.f1( ) -- execution pointer is set to the first item in B's vtable
    2. call A::f1( ) -- execution pointer is set to the first item in A's vtable
    3. call f2( ) --
    here is where question comes. Since the execution pointer is still pointing to the code segment belonging to A::f1( ), how could it change to B::f2?

    Thanks.

  5. #5
    Lindley is offline Elite Member Power Poster
    Join Date
    Oct 2007
    Location
    Seattle, WA
    Posts
    10,895

    Re: vtable question: why its own method is called rather than the parent's one?

    I don't know the specifics of the vtable, but if you've got a B* pointer to a B object, I don't see why A's methods would get involved at all.

  6. #6
    Join Date
    May 2008
    Posts
    6

    Re: vtable question: why its own method is called rather than the parent's one?

    I guess it can be explained by "this" pointer. In A::f1( ), the f2( ) is called actually in the form of "this->f2( )". Therefore, when we call b->f1( ), the "this" pointer is pointing to B object, which cause "this->f2( )" jump to B's f2( ).

    As Lindley indicated, the interesting thing happened if we change the main function a little bit:

    Code:
    int main (...)
    {
    B * b = new B();
    ((A*)b)->f1( );
    delete b;
    }
    Any ideas about the output from this code?

  7. #7
    Lindley is offline Elite Member Power Poster
    Join Date
    Oct 2007
    Location
    Seattle, WA
    Posts
    10,895

    Re: vtable question: why its own method is called rather than the parent's one?

    It should be the same, since the actual object is a B, the method called will be B's method where one exists. A method from A will only be called if it is non-virtual or if B does not define an overriding function.

    As to what I said before:
    I don't know the specifics of the vtable, but if you've got a B* pointer to a B object, I don't see why A's methods would get involved at all.
    There is an exception to that: The constructor of A will be called in the process of calling B's constructor. Also, since you didn't declare A's destructor virtual, which destructor gets called (both or just A's) will depend on what kind of pointer you cast to for the delete call.

  8. #8
    Join Date
    Apr 1999
    Posts
    27,449

    Re: vtable question: why its own method is called rather than the parent's one?

    Quote Originally Posted by haiyeong
    I guess it can be explained by "this" pointer. In A::f1( ), the f2( ) is called actually in the form of "this->f2( )". Therefore, when we call b->f1( ), the "this" pointer is pointing to B object, which cause "this->f2( )" jump to B's f2( ).
    The f2() is a virtual function. The B class has the virtual function implemented. Regardless of which class you're in, if you have a B object, and call a virtual function that is implemented in B, you better get B's implementation called. If this didn't happen, the whole point of using virtual functions would be lost.

    The time things don't work the way I've described is where somewhere in the chain of function calls, the instance of B is lost, and you wind up with an A object. This can occur when you overload a function with references or pointers to A and B. See this article:

    http://en.wikipedia.org/wiki/Double_dispatch

    The other time things do not work is if the virtual mechanism is attempted to be used during object construction. You cannot call a virtual function in a constructor, and have it automatically call the derived version's implementation. In this scenario, it will always call the base class version of the function.
    As Lindley indicated, the interesting thing happened if we change the main function a little bit:
    Code:
    int main (...)
    {
    B * b = new B();
    ((A*)b)->f1( );
    delete b;
    }
    Any ideas about the output from this code?
    Virtualness does not disappear because you casted up. You are still going to call B's methods. If you want to call A's methods, you have to explicitly do it using "A::" (unless you have a scenario as described in the double dispatch description)

    What is more strange is that you cannot call A methods at all if A has a public method and it wasn't overriden in B, and you are using a B object. Do you know why? (I know why, but asking you anyway )

    Example:
    Code:
    #include <stdio.h>
    
    class A
    {
        public: virtual void f1()
        {
            f2();
        }
    
        public: virtual void f2()
        {
            printf("A.f2()\n");
        }
    
        public: virtual void f3()
        {
             printf("A.f3()\n");
        }
    };
    
    class B : A
    {
        public: virtual  void f1()
        {
            A::f1();
        }
        public: virtual void f2()
        {
            printf("B.f2()\n");
        }
    };
    
    int main(int argc, char** argv)
    {
        B b;
        b.f3();  // error, Cannot call f3().
    }
    Regards,

    Paul McKenzie

  9. #9
    Join Date
    Apr 1999
    Location
    Altrincham, England
    Posts
    4,470

    Re: vtable question: why its own method is called rather than the parent's one?

    Quote Originally Posted by haiyeong
    what I was thinking is how the execution pointer been moved back from A::f1( ) back to B.

    vtable for A:
    0: pointer to A::f1
    4: pointer to A::f2

    vtable for B:
    0: pointer to B::f1
    4: pointer to B::f2

    The execution process would be:
    1. call b.f1( ) -- execution pointer is set to the first item in B's vtable
    2. call A::f1( ) -- execution pointer is set to the first item in A's vtable
    This is where your thinking has gone wrong. The object is a B, it only has a B vtable - when the code in A::f1 is executed, the vtable is still B's, not A's. Only when the object is of type A will you get an A vtable (e.g. during construction/destruction when it's in A's constructor or destructor, if you create an object of type A, or if you slice a B object by passing it to a function that takes an a argument by value).
    Correct is better than fast. Simple is better than complex. Clear is better than cute. Safe is better than insecure.
    --
    Sutter and Alexandrescu, C++ Coding Standards

    Programs must be written for people to read, and only incidentally for machines to execute.

    --
    Harold Abelson and Gerald Jay Sussman

    The cheapest, fastest and most reliable components of a computer system are those that aren't there.
    -- Gordon Bell


  10. #10
    Join Date
    May 2008
    Posts
    6

    Re: vtable question: why its own method is called rather than the parent's one?

    Thanks guys. I know that B::f2( ) should be called otherwise polymorphism means nothing. I guess I was puzzled by the virtual function on the execution level or compiler level, how this dynamic call can be implemented when compiling or executing code. I may find a textbook on compiler design to recall those knowledge.

    BTW, http://en.wikipedia.org/wiki/Double_dispatch is an interesting article. Thanks again.

  11. #11
    Join Date
    May 2008
    Posts
    6

    Re: vtable question: why its own method is called rather than the parent's one?

    Hi Paul,

    I tried the f3( ) method, it works in my compiler: g++ (GCC) 4.2.3 (Ubuntu 4.2.3-2ubuntu7). why you say " b.f3(); // error, Cannot call f3()."?

    quote:
    >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
    Code:
    int main(int argc, char** argv)
    {
        B b;
        b.f3();  // error, Cannot call f3().
    }
    >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

  12. #12
    Join Date
    Nov 2002
    Location
    Los Angeles, California
    Posts
    3,863

    Re: vtable question: why its own method is called rather than the parent's one?

    if you got it to compile then you changed it.

    Paul put something subtle in B definition
    Wakeup in the morning and kick the day in the teeth!! Or something like that.

    "i don't want to write leak free code or most efficient code, like others traditional (so called expert) coders do."

  13. #13
    Join Date
    Apr 1999
    Posts
    27,449

    Re: vtable question: why its own method is called rather than the parent's one?

    Quote Originally Posted by haiyeong
    Hi Paul,

    I tried the f3( ) method, it works in my compiler: g++ (GCC) 4.2.3 (Ubuntu 4.2.3-2ubuntu7). why you say " b.f3(); // error, Cannot call f3()."?
    Did you try the *exact* code I posted? Don't change anything. Just copy and paste it into your compiler's editor. As a matter of fact, I got the A and B classes from the first code you posted.

    If you still do not get an error, your compiler is broken.

    Regards,

    Paul McKenzie

  14. #14
    Join Date
    May 2008
    Posts
    6

    Re: vtable question: why its own method is called rather than the parent's one?

    Oh, I see. The trick is "public B : A" rather than "public B : public A". The default is "private" in C++ derivation, therefore method f3( ) in B is a private member. I tried it again through copy&paste this time, and there IS an error.
    Last edited by haiyeong; May 31st, 2008 at 06:06 PM.

  15. #15
    Join Date
    Nov 2002
    Location
    Los Angeles, California
    Posts
    3,863

    Re: vtable question: why its own method is called rather than the parent's one?

    Wakeup in the morning and kick the day in the teeth!! Or something like that.

    "i don't want to write leak free code or most efficient code, like others traditional (so called expert) coders do."

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured