The following C++ statement
A b;
doesn't mean "b is an object of type A", but rather "b is an instance of A" (i.e. an object).
Compare those two lines:
Class obj = new Class(); // java
Class* obj = new Class(); // C++
I re-wrote something similar to your example with pointers:
class A {
public:
virtual void f() { Serial.println("A"); }
};
class B : public A {
public:
virtual void f() { Serial.println("B"); }
};
void setup() {
A* obj; // base-class pointer
Serial.begin(115200);
obj = new A();
obj->f(); // base class version
obj = new B();
obj->f(); // child class version
}
void loop() {
}
The serial monitor shows
A
B