Перегрузка будет означать, что у вас есть две функции с одним и тем же именем, но с разными параметрами. Здесь дело не в этом.
Пример:
int functionA() { /*...*/ };
int functionA(int someParameter) { /*...*/ };
Переопределение означает переписывание функции с теми же параметрами в подклассе. Это то, что вы привели в качестве примера.
Это часть определения. Теперь о дизайне:
Когда у вас есть чисто виртуальная функция, конкретные подклассы должны переопределить ее. Таким образом, добавляя чисто виртуальную функцию, вы гарантируете, что все подклассы предоставляют одинаковый набор функций (= интерфейс). Это похоже на пример кода.
Но это не очень хороший пример, так как конкретный суперкласс уже реализует функциональность по умолчанию для foo (). Когда существует абстрактный подкласс, который переопределяет его как чисто виртуальный, для меня это признак того, что иерархия классов имеет недостатки, поскольку подкласс (и вызывающие функции foo ()) обычно должны иметь возможность использовать реализацию по умолчанию. С таким абстрактным примером это немного сложно объяснить, но подобная иерархия немного подозрительна.