Derived classes and function hiding

Viewed 48

Consider the following example:

class A {
    public:
    int foo() { return 1; }
    int bar() { return foo(); }
};

class B : public A {
    int foo() { return 2; }
};

int main() {
    auto b = B();
    return b.bar();
}

Why does main() return 1 insted of 2? Is foo() not the most visible function for B? Does there exist some override-feature for non-virtual classes to completely replace a function in every call? I know of CRTP, but it is quite verbose in this simple case.

2 Answers

This is what virtual is for!

The function you're calling, A::bar(), doesn't know that the full object is a B. It only knows the A context. You can also think of it as doing a call to this->foo(), where this is an A* (because it is).

If foo were virtual, the call would work as you expect: looking up the most-derived type at runtime and using that instead.

Polymorphism isn't an "independent concept" from this; it's literally this concept.

The definition of class A is equivalent to: (see this-pointer)

class A {
    public:
    int foo() { return 1; }
    int bar() { return this->foo(); }
};

During the linking, bar uses the definition of foo in class A.

Below is a version delivering the result you expect:

#include <iostream>
#include <string>

class A {
    public:
    int foo() { return 2; }
};

class B : public A {
    
    public:
    int foo() { return 1; }
    int bar1() { return foo(); }
    int bar2() { return A::foo(); }
};

int main() {
    auto b = B();
    std::cout<<b.bar1()<<std::endl;
    std::cout<<b.bar2()<<std::endl;
}


Output:
1
2
Related