When the compiler has more than one way to resolve a symbol, it has to choose which one has precedence unless the code tells it otherwise. What you are expecting is the overloading to take precedence over the overriding. (over, over, over, aaaaack! Sorry, got 'over'whelmed).
This example has B inheriting a virtual method in which the subclass provides an overloaded version. Overloads are for methods in the same class using the same method name but different signatures. Since B is a subclass of A, it is overriding f(), which means it cannot also be an overload at the same time. This is why it is being hidden.
For class A, declaring method
virtual void f() {}
as virtual means that method will be resolved using a certain set of rules that are not consistent with your declaration of b.
B *b = new B();
By creating 'b' as an instance of "B", the compiler has no need to use the virtual nature of the method of the same name in "A".
If you had declared 'b' like this
B *b = new A();
then the call b->f(); would indeed refer to the method in A by making use of the virtual resolution.