Polymorphism or inheritance?-Collection of common programming errors

The function int f(int) in class B “hides” the function with the same name and signature in its base class.

So, when you call b.f(3);, and the variable b has type B, you are calling B::f.

Virtual functions are only needed if you want b.f(3) to call B::f in cases where the type of the variable b is A&, but the object it refers to has runtime type B. In that situation, the function called would be B::f if A::f is virtual, but A::f is called if non-virtual.

Virtual function calls take the runtime type of objects into account even if they’re used via a pointer or reference to a base class. But B b; b.f(3) is a call to B::f regardless of whether A::f even exists, never mind whether it’s virtual or non-virtual.