Rachel
Rachel

Reputation: 11

Overriding Non-Virtual methods?

Below is some code that is intended to show when the virtual method is overridden. It outputs: B B A A B A Is this correct? I thought the bar method could not be overridden...?

#include <iostream>
using namespace std;


class A
{
public:
    virtual void foo(){cout<<"A"<<endl;}
            void bar(){cout<<"A"<<endl;}
};

class B : public A
{
public:
    void foo(){cout<<"B"<<endl;}
    void bar(){cout<<"B"<<endl;}
};

int main()
{
    B b;
    A * pA = new A;
    A * pA2 = &b;
    b.foo(); b.bar();
    pA->foo(); pA->bar();
    pA2->foo(); pA2->bar();

}    

Upvotes: 1

Views: 332

Answers (4)

Michael
Michael

Reputation: 2250

It is correct, the pA2->bar() call is not overridden. Even though it's a B object, you cast it to an A and the compiler calls A member functions for A classes.

foo() is virtual, so included inside of the class B is a pointer to which version of foo() is correct for the class, regardless of where it's cast to.

This inclusion is called a pointer to a virtual function table. As soon as your class has on virtual member, a static function table is created for it (and also will include any other subsequent virtual functions), additionally a constant hidden member pointer points to this table. When you cast an object the function table is unchanged, any virtual functions will stay 'attached' to the original type.

PS, don't forget to delete pA... you currently have a memory leak :)

Upvotes: 0

Jack
Jack

Reputation: 133557

I don't see anything wrong:

B b;
b.foo(); b.bar();

You declare and initialize an instance of B, compile type is B, runtime type is B. Polymorphism is not needed (nor it can be achieved, since there is no pointer involved).

A * pA = new A;
pA->foo(); pA->bar();

You declare a pointer to A and initialize it with an instance of A. Polymorphism works even if it is not necessary in this case, so foo() and bar() from A are called.

A * pA2 = &b;
pA2->foo(); pA2->bar();

You declare a pointer to A and initialize it with a reference to B. Compile time type is A*, runtime type is B*. Polymorphism through virtual function is applied, so the virtual method is B::foo() while the non-virtual is A::bar()

Upvotes: 2

Darius Makaitis
Darius Makaitis

Reputation: 880

The first two outputs should both be B because you are calling foo() and bar() on an object of type B. Since you're not using a pointer, the compiler knows it's an object of type B and therefore does not need to consult the vtable to invoke the method, so even though bar() is not virtual, the compiler knows to use the B implementation.

The next two outputs should both be A because you're calling foo() and bar() on a pointer to an object of type A. In this case, foo() is virtual, and the vtable is pointing to the A implementation of the method. bar() is not virtual, so the compiler decides to use the A implementation.

The final two outputs should be B and A because you're calling foo() and bar() on a pointer to an object of type B. In this case, foo() is virtual, and the vtable is pointing to the B implementation of the method. bar() is not virtual, so the compiler decides to use the A implementation since you're using a pointer to an object of type A.

Upvotes: 1

CS Pei
CS Pei

Reputation: 11047

b.foo() gives B,

b.bar() also gives B which hides A::bar(). It is not overriding, it is name hiding.

pA->foo() gives A, pA->bar() gives A,

pA2->foo() gives B since it is a virtual function.

pA2->bar() gives A since it is not a virtual function. It is statically linked and it calls A::bar().

Upvotes: 1

Related Questions