Why is a call to a shadowing non-virtual member function in the derived class not calling the base class member function?
Asked Answered
S

3

125

Let's assume this scenario in Visual C++ 2010:

#include <iostream>

using namespace std;

struct Base {
    void Display() {
        cout << "Base: Non-virtual display." << endl;
    };
    virtual void vDisplay() {
        cout << "Base: Virtual display." << endl;
    };
};

struct Derived : Base {
    void Display() {
        cout << "Derived: Non-virtual display." << endl;
    };
    virtual void vDisplay() {
        cout << "Derived: Virtual display." << endl;
    };
};

int main() {
    Base ba;
    Derived de;

    ba.Display();
    ba.vDisplay();
    de.Display();
    de.vDisplay();
};

Theoretically, the output of this little application should be:

Base: Non-virtual display.
Base: Virtual display.
Base: Non-virtual display.
Derived: Virtual display.

because the Display method of the Base class is not a virtual method so the Derived class should not be able to override it. Right?

The problem is that when I run the application, it prints this:

Base: Non-virtual display.
Base: Virtual display.
Derived: Non-virtual display.
Derived: Virtual display.

So either I don't understand the concept of virtual methods or something strange happens in Visual C++.

What is the explanation?

Sometime answered 17/6, 2012 at 0:10 Comment(1)
you would absolutely have Base: Non-virtual display. when changing your line to de.Base::Display().Cavie
A
180

Yep, you are misunderstanding a little.

The method of the same name on the derived class will hide the parent method in this case. You would imagine that if this weren't the case, trying to create a method with the same name as a base class non-virtual method should throw an error. It is allowed and it's not a problem - and if you call the method directly as you have done it will be called fine.

But, being non-virtual, C++ method lookup mechanisms that allow for polymorphism won't be used. So for example if you created an instance of your derived class but called your 'Display' method via a pointer to the base class, the base's method will be called, whereas for 'vDisplay' the derived method would be called.

For example, try adding these lines:

Base *b = &ba;
b->Display();
b->vDisplay();
b = &de;
b->Display();
b->vDisplay();

...and observe the output as expected:

Base: Non-virtual display.
Base: Virtual display.
Base: Non-virtual display.
Derived: Virtual display.

Apomixis answered 17/6, 2012 at 0:18 Comment(6)
Hi @sje397, thank you for your reply. Can you write an example of calling the method, as you said, via a pointer to the base class? Thank you!Sometime
also as I said you can ALSO call the (non-virtual) base method from the derived instance, using scope resolution syntax.Cavie
So, just to be sure, I can define a method in base class, and override it in derived class, irrespective of declaring it as virtual or not. The only difference is that if a base pointer points to a derived class object, then calling that method will cal the base class' method if it is not virtual, and the derived class' method if it is virtual. Is that right? Is there any other difference?Anchoress
@Cupidvogel Yep, that's correct. Declaring it 'virtual' means C++ will use mechanisms to support polymorphism and check to see if there is a more derived version of the method when you call via a base class pointer. I can't think of any other difference.Apomixis
Is it enough to change the header file only? Or, must the source be compiled with the "virtual" keyword?Thorn
@PaulKnopf The 'virtual' keyword is not allowed on a definition outside of the class declaration itself. So no you don't have to add it to the cpp file. You will need to recompile though, of course.Apomixis
S
38

Yes, you have misunderstood a little:

Pure virtual functions

virtual void fun1() = 0 -> must be overridden in the derived class

Virtual functions:

virtual void fun2() -> can be overridden

Normal functions:

void fun3() -> don't override it

In order to achieve runtime polymorphism, you need to override virtual functions in C++.

Skald answered 17/11, 2016 at 17:32 Comment(0)
R
11

I think it might be also better to look at it in the context of static vs dynamic binding.

If the method is non-virtual (it's already by default in C++ unlike Java), then the method binds to it's caller at compile time which is impossible to know the actual object that will be pointed at runtime. So, variable type is all that matters which is the 'Base'.

Riojas answered 3/11, 2017 at 14:2 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.