简体   繁体   中英

Overriding Non-Virtual methods?

Below is some code that is intended to show when the virtual method is overridden. It outputs: BBAABA 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();

}    

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()

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

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.

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 :)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM