Jakie są różnice między nadpisywaniem funkcji wirtualnych a ukrywaniem funkcji nie-wirtualnych?

Biorąc pod uwagę następujący fragment kodu, jakie są różnice w wywołaniach funkcji? Co to jest ukrywanie funkcji? Czym jest funkcja nadrzędna? Jak odnoszą się do przeciążeń funkcji? Jaka jest różnica między tymi dwoma? Nie mogłem znaleźć dobrego opisu w jednym miejscu, więc pytam tutaj, abym mógł skonsolidować informacje.

class Parent {
  public:
    void doA() { cout << "doA in Parent" << endl; }
    virtual void doB() { cout << "doB in Parent" << endl; }
};

class Child : public Parent {
  public:
    void doA() { cout << "doA in Child" << endl; }
    void doB() { cout << "doB in Child" << endl; }
};

Parent* p1 = new Parent();
Parent* p2 = new Child();
Child* cp = new Child();

void testStuff() {
  p1->doA();
  p2->doA();
  cp->doA();

  p1->doB();
  p2->doB();
  cp->doB();
}

questionAnswers(5)

yourAnswerToTheQuestion