Hide virtual function with non-virtual override
Asked Answered
T

1

12

Having

#include <iostream>

using namespace std;

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

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

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

int main() {
    C c;
    B* b = &c;
    b->foo();

    return 0;
}

The output is C, but I expected B.

I didn't declare B::foo() with the virtual modifier, so I expect the function call to be determined by the static type (no polymorphism).

Why is C::foo() being called?

Is it possible to provide a non-virtual function in a derived class, that hides the virtual function in the base? What signature should the derived member function have so that b->foo() calls it, and not (b->*&A::foo)()

Trapani answered 18/6, 2014 at 12:55 Comment(10)
B::foo() is virtual. The premise of your question is wrong.Selfpossession
The virtual is inherited from A. You do not need to re-specify it (although I recommend that you do for clarity).Patellate
thanks! do i delete the question?Trapani
@I've given your question a more accurate title. It is a reasonable question and can be given a good answer. Now that you know the issue, why don't you edit your question to match reality, so others can benefit from a good explanation? (i.e. "I didn't declare B::foo() as virtual" instead of ``B::foo()` isn't virtual")Leeland
no I disagree with deleting this question. @Selfpossession several people dont know that. IMHO an answer with a small explanation is needed. Unless it is a duplicate.Jackfish
As it stands, the question is one of these: meta.#259231Leeland
Instead of tagging on virtual to B::foo, I suggest instead to tag on override.Edgeways
Actually, I made the edits I was thinking of for you. I hope this preserves the essence of your question, while no longer assuming "facts" contrary to reality.Leeland
BTW: ideone.com/MNNKBi A default argument would probably be better than ...Leeland
Related: https://mcmap.net/q/1012102/-define-the-method-once-to-be-virtual-in-the-inheritance-hierarchy-to-make-polymorphism-to-work/103167Leeland
L
5

The principle of virtual inheritance of a member function is is a direct consequence of the C++ Standard:

10.3/2: If a virtual member function vf is declared in a class Base and in a class Derived, derived directly or indirectly from Base, a member function vf with the same name, parameter-type-list , cv-qualification, and refqualifier (or absence of same) as Base::vf is declared, then Derived::vf is also virtual.

So regardless of the level of inheritance, the function will be virtual in all the classes derived somehow from A. There is no need to put the keyword virtual.

The goal of this polymorphic approach is to ensure that you always call the appropriate function corresponding to the real idendity of your object, regardless the fact that you use a pointer to a base or a pointer to the real class of the object. This is why you obtain "C" !

In this related SO question I explain a trick to give the impression of removing virtuality at one single level, using multiple inheritance. However it can be done only for a single level (you should do it for the class of your base pointer).

*By the way, you could write pb->B::foo(); no need of *&.

Local answered 19/2, 2015 at 23:39 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.