views:

103

answers:

3

I'm learning about polymorphism, and I am confused by this situation: Let's say I have the following C++ classes:

class A{
    ...
    virtual void Foo(){
        Boo();
    }
    virtual void Boo(){...}
}

class B : public A{
    ...
    void Foo(){
        A::Foo();
    }  
    void Boo(){...}
}

I create an instance of B and call its Foo() function. When that function calls A::Foo(), will the Boo() method used be that of class A or B? Thanks!

+2  A: 

Since Boo() is virtual, the derived class' override is called.

Boo(); is just a short-hand for this->Boo();, where you can see that a virtual function is called through a pointer. (this is of type A* const within Foo().) And virtual functions called through a reference or a pointer will always call the override in the most-derived class (except when called from a constructor or destructor).

sbi
Thanks a bunch.
ODdol
+1  A: 

Hi Odol,

Inside A,

virtual void Foo(){
        Boo();
    }

gets translated to this->Boo() ;since Boo is declared virtual in A, the derived class's method Boo gets called. Try not declaring Boo as virtual in A just for experimentation -- you'd see that A->Boo() is getting called.

Arpan

Fanatic23
+2  A: 

Unless you qualify a function call with the class, all method calls will be treated equal, that is dynamic dispatch if virtual, static dispatch if not virtual. When you fully qualify with the class name the method you are calling you are effectively disabling the dynamic dispatch mechanism and introducing a direct method call.

class A{
    virtual void Foo(){
        Boo();           // will call the final overrider
        A::Boo();        // will call A::Boo, regardless of the dynamic type
    }
    virtual void Boo();
};
class B : public A{
    void Foo(){
        //Foo();         // Would call the final overrider 
                         // (in this case B: infinite recursion)
        A::Foo();        // Will call A::Foo, even if the object is B
    }  
    void Boo();
};

The implicit this pointer is not an important part of the discussion here, as exactly the same happens when the call is made with an explicit object:

B b;
b.Foo();    // will call B::Foo -- note 1
b.A::Foo(); // will call A::Foo

Note 1: in this example, the compiler can elide the dynamic dispatch mechanism as it knows the concrete type of the instance (it sees the definition and it is not a reference/pointer) but you can imagine the same would happen if b was a reference, or equivalently if it was a pointer with -> instead of .

David Rodríguez - dribeas